home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Graphics Plus
/
Graphics Plus.iso
/
general
/
viewers
/
polyview
/
polyvw31.lha
/
Polyview3.1
/
new
/
pvpoly.c
< prev
next >
Wrap
C/C++ Source or Header
|
1993-08-24
|
102KB
|
3,266 lines
/*****************************************************************************
* NCSA Polyview 3.1 *
* *
* Version 3.1 changes and additions by Gilles Bourhis. *
* Version 3 changes and additions by Marc Andreessen. *
* Version 2 by Brian Calvert. *
* *
* Software Development Group *
* National Center for Supercomputing Applications *
* University of Illinois at Urbana-Champaign *
* *
* This is BETA release software. As such it may contain software bugs and *
* exhibit inconsistencies. *
* *
* Please send bug reports to polyview@ncsa.uiuc.edu. *
* *
* Copyright (c) 1992 The Board of Trustees of the University of Illinois. *
* *
* Permission to use, copy, and modify this software and its *
* documentation for educational, research, and non-profit purposes is *
* hereby granted, provided that the above copyright notice, the original *
* authors names, and this permission notice appear in all such copies. *
* Any distribution of this software requires the explicit and written *
* authorization of the authors. *
* *
* The University of Illinois makes no representations about the *
* suitability of this software for any purpose. It is provided "as is" *
* without warranty of any kind. *
*****************************************************************************/
/* $Id: pvpoly.c,v 1.5 93/08/24 10:28:53 gbourhis Exp $ */
#ifdef RCSLOG
$Log: pvpoly.c,v $
* Revision 1.5 93/08/24 10:28:53 gbourhis
* Add "Credits" entry in Props menu.
*
* Revision 1.4 93/08/13 12:46:55 gbourhis
* Add handling of the "Save RGB" dialog box. Better transcript. Change
* Version Number
*
* Revision 1.3 93/07/13 16:42:47 gbourhis
* move and use delete_poly(). When close with OK the sphere stuff window,
* check if the sphere has been modified by the user.
*
* Revision 1.2 93/06/24 16:32:39 gbourhis
* add remote_movecursor & remote_movecursorend functions
*
* Revision 1.1 1992/09/18 10:55:26 marca
* Initial revision
*
#endif
#include "pv.h"
#include <X11/keysym.h>
#define PI 3.14159265
/* This should be moved. */
#ifdef __sgi
static Boolean use_pups = FALSE;
/* Return the overlay window of the widget. */
static Window overlayWindow(Widget w)
{
Arg args[1];
Window overlayWindow;
XtSetArg(args[0], use_pups?GlxNpopupWindow:GlxNoverlayWindow,
&overlayWindow);
XtGetValues(w, args, 1);
return (overlayWindow);
}
static XmxCallback (overlayExposeCB)
{
GLXwinset (XtDisplay (w), ((GlxDrawCallbackStruct *)call_data)->window);
color (0);
clear ();
return;
}
#endif /* __sgi */
/* --------------------------- dither routines ---------------------------- */
/* Shade pattern masks. Range from 0 through 100% by 6.25% intervals. */
static unsigned short ShadePattern[18][16];
/* DitherMatrix and CreateShadePattern adapted from Peter Burger and Duncan */
/* Gillies, "Interactive Computer Graphics", Addison-Wesley, 1989. */
static short DitherMatrix[4][4] = {
{1, 9, 3, 11},
{13, 5, 15, 7},
{4, 12, 2, 10},
{16, 8, 14, 6}
};
static void CreateShadePatterns()
{
int i, row;
short sval, val;
/* Create a total of 18 levels of shading. */
for (i = 0; i <= 17; i++)
{
/* For each row of the DitherMatrix, calculate the row */
/* value for the appropriate ShadePattern rows. */
for (row = 0; row < 4; row++)
{
/* Build the DitherMatrix row value. */
sval = ((DitherMatrix[row][0]<=i)?0x8:0x0) |
((DitherMatrix[row][1]<=i)?0x4:0x0) |
((DitherMatrix[row][2]<=i)?0x2:0x0) |
((DitherMatrix[row][3]<=i)?0x1:0x0);
/* Build the value into a full ShadePattern row */
val = (((((sval<<4)|sval)<<4)|sval)<<4)|sval;
/* Store the value in the appropriate rows of the */
/* ShadePattern array. */
ShadePattern[i][row] = val;
ShadePattern[i][row+4] = val;
ShadePattern[i][row+8] = val;
ShadePattern[i][row+12] = val;
}
}
}
/* Create patterns that are used by various windows. Patterns */
/* 1 through 18 are 0% through 100% solid screens. Pattern 0 is */
/* already a solid pattern. */
void init_patterns (void)
{
int i;
CreateShadePatterns();
for (i = 0; i <= 17; i++)
defpattern(i+1, 16, ShadePattern[i]);
}
/* ------------------------------- best_fit ------------------------------- */
static int best_fit (state_t *state, window_t *win)
{
float tan_value, va_rad;
va_rad = (PI/180.0) * (WIN_FOV(win)/(20.0));
tan_value = 2*ftan(va_rad);
/* Adjust rho sufficiently to allow the worst-case view to fit */
/* within the win. The worst-case view has a width of */
/* WIN_MAXWIDTH(). */
WIN_SFROM(win)[RHO] = WIN_MAXWIDTH(win) / tan_value;
/* Adjust the coordinates back to cartesian space. */
sphere_to_cart(WIN_SFROM(win)[RHO], WIN_SFROM(win)[THETA],
WIN_SFROM(win)[PHI],
&(WIN_CFROM(win)[X]), &(WIN_CFROM(win)[Y]),
&(WIN_CFROM(win)[Z]) );
WIN_CFROM(win)[X] += WIN_AT(win)[X];
WIN_CFROM(win)[Y] += WIN_AT(win)[Y];
WIN_CFROM(win)[Z] += WIN_AT(win)[Z];
return TRUE;
}
/* ---------------------------- init_polyview ----------------------------- */
/* init_polyview initializes the internals of the polyview data structure. */
/* This function is called when a new polyview is created or the data */
/* associated with the window changes. The function requires a pointer */
/* to the system state, the window to initialize, and whether to do a reset */
/* or not. Returns ST_OKAY if no error occurs. */
int init_polyview(state_t *state, window_t *win, int reset)
{
/* Make sure that there is a structure to initialize. */
assert (win != NULL);
/* We go through here twice for some reason, for the first window.
The first time all the stats are max=BIG and min=0, so maxwidth
makes no sense. The second time through, they're OK, but by then
it's too late to change move_step. */
/* Calculate maximum possible width of view. */
WIN_MAXWIDTH(win) =
fhypot(WIN_STATS(win,PX).max -
WIN_STATS(win,PX).min,
fhypot(WIN_STATS(win,PY).max -
WIN_STATS(win,PY).min,
WIN_STATS(win,PZ).max -
WIN_STATS(win,PZ).min));
if (WIN_MAXWIDTH(win) < FLT_MAX)
WIN_STEP(win) = WIN_MAXWIDTH(win) * 0.05; /* was 0.025 */
else
WIN_STEP(win) = 0.1;
/* If the view is to be reset, recalculate the best view of */
/* the data. This means resetting the reference point, */
/* resetting the fov angle, placing the camera in the */
/* positive y direction from the focus point, and calculating */
/* a best-fit viewing distance. */
if (reset)
{
/* Calculate a new reference point. */
WIN_AT(win)[X] = (WIN_STATS(win,PX).min +
WIN_STATS(win,PX).max) * 0.5;
WIN_AT(win)[Y] = (WIN_STATS(win,PY).min +
WIN_STATS(win,PY).max) * 0.5;
WIN_AT(win)[Z] = (WIN_STATS(win,PZ).min +
WIN_STATS(win,PZ).max) * 0.5;
/* Reset the fov angle. */
WIN_FOV(win) = DEF_FOV;
WIN_PROJECTION(win) = PERSPECTIVE;
/* Calculate a new camera point. */
WIN_SFROM(win)[RHO] = 1.0;
WIN_SFROM(win)[THETA] = (90.0*PI)/180.0;
WIN_SFROM(win)[PHI] = (90.0*PI)/180.0;
WIN_TWIST(win) = 0;
win->twist_tmp = 0;
/* Pick all of the objects. */
PickAll(state, win);
/* best fit moves the camera along its current */
/* line of sight to a position which guarantees */
/* that the entire object will be visible. It */
/* modifies both the cartesian and spherical */
/* representations of the coordinates. */
best_fit(state, win);
/* should the init_window routine do this? */
WIN_MOVE(win) = FROM;
}
else
{
/* Set up the default names of the data sets. */
strcpy(WIN_PXNAME(win), DEF_PXNAME);
strcpy(WIN_PYNAME(win), DEF_PYNAME);
strcpy(WIN_PZNAME(win), DEF_PZNAME);
strcpy(win->vname[PCOORD], "pcoord");
strcpy(WIN_PLISTNAME(win), DEF_CONNECTNAME);
strcpy(WIN_VSCALARNAME(win), DEF_VSCALARNAME);
/* When shadow data is displayed, use vertices. */
set_over_shadow_vertices(state, win);
}
return ST_OKAY;
}
/* ---------------------------- backdrop code ----------------------------- */
static void DrawBackgroundPolygon (window_t *win,
int c1, int c2, int c3, int c4)
{
float vv[2];
zbuffer (FALSE);
shademodel (GOURAUD);
mmode (MSINGLE);
pushmatrix ();
ortho2 (0.0, 1.0, 0.0, 1.0);
bgnpolygon ();
vv[0] = 0.0;
vv[1] = 0.0;
cpack (c1); v2f (vv);
cpack (c2); vv[0] = 1.0; v2f (vv);
cpack (c3); vv[1] = 1.0; v2f (vv);
cpack (c4); vv[0] = 0.0; v2f (vv);
endpolygon ();
popmatrix ();
mmode (MVIEWING);
shademodel (WIN_SHADE(win));
zbuffer (TRUE);
return;
}
static void draw_backdrop (window_t *win)
{
/* This handles clearing the window now too. */
switch (win->backdrop)
{
case PV_PALETTE_BACKG_BLACK:
czclear(0, gstate->zmin);
break;
case PV_PALETTE_BACKG_WHITE:
czclear(0xffffff, gstate->zmin);
break;
case PV_PALETTE_BACKG_GREY:
czclear(0x6f6f6f, gstate->zmin);
break;
case PV_PALETTE_BACKG_BLUE:
czclear(0x9f0000, gstate->zmin);
break;
case PV_PALETTE_BACKG_RED:
czclear(0x00009f, gstate->zmin);
break;
case PV_PALETTE_BACKG_RGBY:
czclear(0, gstate->zmin);
DrawBackgroundPolygon (win, 0x0000ff, 0x00ffff, 0x00ff00, 0xff0000);
break;
case PV_PALETTE_BACKG_RGBLUE:
czclear(0, gstate->zmin);
DrawBackgroundPolygon (win, 0x00ff00, 0xff0000, 0x0000ff, 0x0000ff);
break;
case PV_PALETTE_BACKG_RBBLACK:
czclear(0, gstate->zmin);
DrawBackgroundPolygon (win, 0xff0000, 0x0000ff, 0x0, 0x0);
break;
case PV_PALETTE_BACKG_BLUEHORIZ:
czclear(0, gstate->zmin);
DrawBackgroundPolygon (win, 0x9f0000, 0x9f0000, 0x0, 0x0);
break;
case PV_PALETTE_BACKG_REDHORIZ:
czclear(0, gstate->zmin);
DrawBackgroundPolygon (win, 0x00009f, 0x00009f, 0x0, 0x0);
break;
case PV_PALETTE_BACKG_GREENHORIZ:
czclear(0, gstate->zmin);
DrawBackgroundPolygon (win, 0x009f00, 0x009f00, 0x0, 0x0);
break;
case PV_PALETTE_BACKG_YELLOWHORIZ:
czclear(0, gstate->zmin);
DrawBackgroundPolygon (win, 0x009f9f, 0x009f9f, 0x0, 0x0);
break;
case PV_PALETTE_BACKG_BLUESKY:
czclear(0, gstate->zmin);
DrawBackgroundPolygon (win, 0x0, 0x0, 0x9f0000, 0x9f0000);
break;
case PV_PALETTE_BACKG_REDSKY:
czclear(0, gstate->zmin);
DrawBackgroundPolygon (win, 0x0, 0x0, 0x00009f, 0x00009f);
break;
case PV_PALETTE_BACKG_GREENSKY:
czclear(0, gstate->zmin);
DrawBackgroundPolygon (win, 0x0, 0x0, 0x009f00, 0x009f00);
break;
case PV_PALETTE_BACKG_YELLOWSKY:
czclear(0, gstate->zmin);
DrawBackgroundPolygon (win, 0x0, 0x0, 0x009f9f, 0x009f9f);
break;
case PV_PALETTE_BACKG_BLUESTREAK:
czclear(0, gstate->zmin);
DrawBackgroundPolygon (win, 0x0, 0x9f0000, 0x0, 0x9f0000);
break;
case PV_PALETTE_BACKG_REDSTREAK:
czclear(0, gstate->zmin);
DrawBackgroundPolygon (win, 0x0, 0x00009f, 0x0, 0x00009f);
break;
case PV_PALETTE_BACKG_GREENSTREAK:
czclear(0, gstate->zmin);
DrawBackgroundPolygon (win, 0x0, 0x009f00, 0x0, 0x009f00);
break;
case PV_PALETTE_BACKG_YELLOWSTREAK:
czclear(0, gstate->zmin);
DrawBackgroundPolygon (win, 0x0, 0x009f9f, 0x0, 0x009f9f);
break;
case PV_PALETTE_BACKG_BLUESMEAR:
czclear(0, gstate->zmin);
DrawBackgroundPolygon (win, 0x9f0000, 0x0, 0x9f0000, 0x0);
break;
case PV_PALETTE_BACKG_REDSMEAR:
czclear(0, gstate->zmin);
DrawBackgroundPolygon (win, 0x00009f, 0x0, 0x00009f, 0x0);
break;
case PV_PALETTE_BACKG_GREENSMEAR:
czclear(0, gstate->zmin);
DrawBackgroundPolygon (win, 0x009f00, 0x0, 0x009f00, 0x0);
break;
case PV_PALETTE_BACKG_YELLOWSMEAR:
czclear(0, gstate->zmin);
DrawBackgroundPolygon (win, 0x009f9f, 0x0, 0x009f9f, 0x0);
break;
}
return;
}
/* --------------------------- redraw_polyview ---------------------------- */
int redraw_polyview(state_t *state, window_t *win)
{
polyview_t *pv;
object_t *obj;
int status;
float maxwidth;
static Matrix ident = {
{1.0, 0.0, 0.0, 0.0}, {0.0, 1.0, 0.0, 0.0},
{0.0, 0.0, 1.0, 0.0}, {0.0, 0.0, 0.0, 1.0}
};
int i, j;
float xaspect, yaspect;
float width, height;
Matrix op;
/* Get a pointer to the root object associated with the win. */
pv = (polyview_t *)WIN_IMAGE(win);
/* We assume we've had XmxWinset called on us in redraw_windows. */
/* Set shading model. */
shademodel (WIN_SHADE(win));
/* Clear window and set backdrop. */
if (win->backdrop)
draw_backdrop (win);
if (WIN_FRAME(win) == NULL)
{
/* Assert if FRAME is null but FRAMELIST is not. Yes,
that should be == not !=. */
assert (WIN_FRAMELIST(win) == NULL);
/* Nothing to draw. */
swapbuffers();
return ST_OKAY;
}
else
{
obj = FRA_ROOTOBJ(WIN_FRAME(win));
}
/* Make sure that the object exists, has information associated */
/* with it, and has a drawing function. */
assert (obj != NULL);
assert (obj->info != NULL);
assert (obj->info->draw_fn != NULL);
/* Save the transformation matrix and the drawing attributes. */
/* Whatever for? We don't have anything loaded when we start
that isn't reloaded every time through. */
pushmatrix();
pushviewport();
pushattributes();
/* Setup transformation matrices. */
maxwidth = WIN_MAXWIDTH(win);
height = (float) pv->dv_height;
width = (float) pv->dv_width;
if (WIN_PROJECTION(win) == ORTHOGRAPHIC)
{
/* Use the spherical viewing distance to determine the scale */
/* to magnify by. */
float scl;
/* Calculate the aspect ratio acaling multiplier. This is */
/* applied to the x-dimension to adjust for the change in */
/* aspect ratio of a resizable win. */
if (width > height)
{
xaspect = height / width;
yaspect = 1.0;
}
else
{
xaspect = 1.0;
yaspect = width / height;
}
/* Initialize the transformation matrix --- this has
to be on the projection stack. */
mmode (MPROJECTION);
loadmatrix(ident);
/* Build an orthographic projection matrix and load it. */
for (i = 0; i < 4; i++)
for (j = 0; j < 4; j++)
op[i][j] = 0.0;
op[0][0] = (2.0 / maxwidth) * xaspect;
op[1][1] = (2.0 / maxwidth) * yaspect;
op[2][2] = (-2.0 / maxwidth);
op[3][3] = 1.0;
multmatrix(op);
/* Now switch back to the viewing matrix and get that
set up. */
mmode (MVIEWING);
loadmatrix (ident);
scl = maxwidth/(WIN_SFROM(win)[RHO]);
/* The Z value was 0.95; what for? */
scale(scl, scl, 1.0);
}
else
{
float dist;
dist = fhypot(WIN_CFROM(win)[X]-WIN_STATS(win,PX).mean,
fhypot(WIN_CFROM(win)[Y]-
WIN_STATS(win,PY).mean,
WIN_CFROM(win)[Z]-
WIN_STATS(win,PZ).mean));
/* This is new. */
loadmatrix (ident);
perspective(WIN_FOV(win),
((float)pv->dv_width / (float)pv->dv_height),
MAX(maxwidth/200,dist-1.1*maxwidth), dist+1.1*maxwidth);
translate(0.0, 0.0, -WIN_SFROM(win)[RHO]);
}
/* These have to match equivalent sets of calls in pvdraw.c,
pvrender.c, pvpick.c, etc etc etc ad nauseum. */
rotate (WIN_TWIST(win), 'z');
rot (90.0-WIN_SFROM(win)[PHI]*180.0/PI,'x');
rot (-90.0-WIN_SFROM(win)[THETA]*180.0/PI,'y');
rot (-90.0, 'x');
translate (-WIN_AT(win)[X],-WIN_AT(win)[Y],-WIN_AT(win)[Z]);
/* Get the image root object and recursively draw the object */
/* structure. */
status = draw_obj_recurs(state, win, obj, obj->info);
/* Restore the transformation matrix, show the work and return. */
popattributes();
popviewport();
popmatrix();
if (win->legend_flag)
draw_legend (state, win);
if (win->credits_flag)
draw_credits (state, win);
swapbuffers();
return status;
}
/* ----------------------------- draw_legend ------------------------------ */
int draw_legend (state_t *state, window_t *win)
{
int i;
if (win != NULL)
{
zbuffer (FALSE);
mmode (MSINGLE);
pushmatrix ();
ortho2
(0.0, (float)WIN_WIDTH(win) - 1.0, 0.0, (float)WIN_HEIGHT(win) - 1.0);
/* Now, (0 0) is (left bottom). We want (left top) = (0 max). */
for (i = 1; i < 255; i++)
{
bgnline ();
PALETTECPACK (i);
p2i (10+i, WIN_HEIGHT(win) - 10);
p2i (10+i, WIN_HEIGHT(win) - 10 - 30);
endline ();
}
popmatrix ();
mmode (MVIEWING);
zbuffer (TRUE);
}
return ST_OKAY;
}
/* ----------------------------- draw_credits ----------------------------- */
int draw_credits (state_t *state, window_t *win)
{
int i;
char *credits;
if (win != NULL)
{
zbuffer (FALSE);
mmode (MSINGLE);
pushmatrix ();
ortho2
(0.0, (float)WIN_WIDTH(win) - 1.0, 0.0, (float)WIN_HEIGHT(win) - 1.0);
cpack (0xffffff);
credits = "NCSA Polyview 3.1, 1993";
cmov2 (WIN_WIDTH(win) - 1 - strwidth(credits), 5);
charstr (credits);
popmatrix ();
mmode (MVIEWING);
zbuffer (TRUE);
}
return ST_OKAY;
}
/* --------------------------- animate_polyview --------------------------- */
int animate_polyview(state_t *state, window_t *win)
{
int i;
if (WIN_FORWARD(win) != 0)
for (i = WIN_SKIP(win); i >= 0; i--)
{
if (WIN_FRAMEID(win) == WIN_FRAMES(win))
{
if (win->bounce)
{
WIN_REVERSE(win) = WIN_FORWARD(win);
WIN_FORWARD(win) = 0;
WIN_FRAMEID(win)--;
WIN_FRAME(win) = get_prev_frame(state, WIN_FRAME(win));
goto done;
}
else
WIN_FRAMEID(win) = 1;
}
else
WIN_FRAMEID(win)++;
WIN_FRAME(win) = get_next_frame(state, WIN_FRAME(win));
}
if (WIN_REVERSE(win) != 0)
for (i = WIN_SKIP(win); i >= 0; i--)
{
if (WIN_FRAMEID(win) == 1)
{
if (win->bounce)
{
WIN_FORWARD(win) = WIN_REVERSE(win);
WIN_REVERSE(win) = 0;
WIN_FRAMEID(win)++;
WIN_FRAME(win) = get_next_frame(state, WIN_FRAME(win));
goto done;
}
else
WIN_FRAMEID(win) = WIN_FRAMES(win);
}
else
WIN_FRAMEID(win)--;
WIN_FRAME(win) = get_prev_frame(state, WIN_FRAME(win));
}
done:
set_redraw(state, win);
send_msg_to_type(state, win, DIALOG, MSG_NEWFRAME);
return ST_OKAY;
}
/* ---------------------------- event_polyview ---------------------------- */
int event_polyview(state_t *state, window_t *win, long dev_id, short data)
{
return ST_OKAY;
}
/* --------------------------- notify_polyview ---------------------------- */
int notify_polyview(state_t *state, window_t *send_win, window_t *recv_win,
int message, va_list args)
{
int status;
window_t *win;
status = ST_OKAY;
switch (message)
{
case MSG_NEWACT:
win = va_arg(args, window_t *);
/* If this is the new active window, set the state to */
/* reflect that fact, and draw the border. */
if (send_win == recv_win)
state->active_windows = recv_win;
else if (recv_win == win)
{
/* Do nothing anymore. */
}
break;
case MSG_NEWFRAME:
case MSG_NEWDATA:
case MSG_NEWPICK:
set_redraw(state, recv_win);
break;
case MSG_VIEWCHG:
case MSG_CLOSING:
/* When the active window closes, there is no active */
/* window. The global active_windows list must be */
/* cleared. */
if (send_win == recv_win)
state->active_windows = NULL;
break;
default:
break;
}
return status;
}
/* ----------------------------- delete_poly ------------------------------ */
/* delete_poly removes associated frames and objects from a window and its */
/* polyview record and then frees the polyview record space, setting the */
/* pointer to NULL. Returns ST_OKAY if no errors occur. */
/* NEVER CALLED */
static int delete_poly (state_t *state, window_t *win)
{
frame_t *frame;
/* Keep deleting frames until there are none left. */
frame = WIN_FRAMELIST(win);
while (frame != NULL)
frame = delete_frame (state, win, frame);
/* Free the space associated with the polyview win. */
PVFREE(win->image);
return ST_OKAY;
}
/* --------------------------- destroy_polyview --------------------------- */
int destroy_polyview(state_t *state, window_t *win)
{
/* This has to shut down the dialog... */
XtUnmanageChild (win->base);
XtDestroyWidget (win->base);
delete_poly(state, win);
if (WIN_ROOTOBJINFO(win) != NULL)
delete_objinfo(state, WIN_ROOTOBJINFO(win));
win->base = NULL;
return ST_OKAY;
}
/* ----------------------------- create_poly ------------------------------ */
/* create poly creates and initializes a polyview record with default values */
/* Returns a pointer to the initialized structure, NULL if an error occurs. */
static polyview_t * create_poly(state_t *state)
{
polyview_t *pv;
/* Create the polyview record. */
pv = (polyview_t *) PVMALLOC(sizeof(polyview_t));
/* Clear all fields initially. */
pv->probe = NULL;
pv->active_window_thread = NULL;
pv->menubar = NULL;
pv->active = NULL;
pv->dtmlockout = NULL;
pv->blast = NULL;
pv->drawing_volume = NULL;
pv->current_select_token = pv->dv_height = pv->dv_width = 0;
pv->loadVsetBox = NULL;
pv->outlineBox = NULL;
pv->linewidthBox = NULL;
pv->sphereBox = NULL;
pv->ray_box = NULL;
pv->rgb_box = NULL;
#ifdef RENDERMAN
pv->rm_box = NULL;
#endif
pv->hdf_box = NULL;
return pv;
}
/* ------------------------------- add_poly ------------------------------- */
/* add_poly creates and initializes a polyview record and adds it to the */
/* specified window. Returns a pointer to the new record, NULL if an error */
/* occurs. */
/* CALLED FROM win_open_polyview */
polyview_t *add_poly (state_t *state, window_t *win)
{
polyview_t *polyview;
/* Create a new polyview record. */
polyview = create_poly(state);
/* Add the record to the win. */
WIN_IMAGE(win) = (void *)polyview;
return polyview;
}
/* ------------------------------------------------------------------------ */
/* --------------------------- POLYVIEW WINDOW ---------------------------- */
/* -------------------------- GUI FUNCTIONALITY --------------------------- */
/* ------------------------------------------------------------------------ */
void GUIpviewResetRender (state_t *state, window_t *win)
{
/* For the given polyview window, we reset the gizmos in the
menubar and elsewhere to match render attributes. */
polyview_t *pv;
assert (win != NULL);
assert (win->type == POLYVIEW);
pv = (polyview_t *)WIN_IMAGE(win);
/* Draw mode. */
XmxRSetToggleState (pv->menubar, PV_PVIEW_DRAW_VERTICES,
(WIN_DRAW(win) == draw_vertices));
XmxRSetToggleState (pv->menubar, PV_PVIEW_DRAW_EDGES,
(WIN_DRAW(win) == draw_edges));
XmxRSetToggleState (pv->menubar, PV_PVIEW_DRAW_HIDDEN,
(WIN_DRAW(win) == draw_hidden_edges));
XmxRSetToggleState (pv->menubar, PV_PVIEW_DRAW_FACES,
(WIN_DRAW(win) == draw_faces));
XmxRSetToggleState (pv->menubar, PV_PVIEW_DRAW_OUTFACES,
(WIN_DRAW(win) == draw_outlined_faces));
/* Drag mode. */
XmxRSetToggleState (pv->menubar, PV_PVIEW_DRAG_NOTHING,
(win->fastdraw_fn == draw_nothing));
XmxRSetToggleState (pv->menubar, PV_PVIEW_DRAG_BOX,
(win->fastdraw_fn == draw_box));
XmxRSetToggleState (pv->menubar, PV_PVIEW_DRAG_VERTICES,
(win->fastdraw_fn == draw_vertices));
XmxRSetToggleState (pv->menubar, PV_PVIEW_DRAG_EDGES,
(win->fastdraw_fn == draw_edges));
XmxRSetToggleState (pv->menubar, PV_PVIEW_DRAG_HIDDEN,
(win->fastdraw_fn == draw_hidden_edges));
XmxRSetToggleState (pv->menubar, PV_PVIEW_DRAG_FACES,
(win->fastdraw_fn == draw_faces));
XmxRSetToggleState (pv->menubar, PV_PVIEW_DRAG_OUTFACES,
(win->fastdraw_fn == draw_outlined_faces));
XmxRSetToggleState (pv->menubar, PV_PVIEW_DRAG_SAMEASDRAW,
(win->fastdraw_fn == NULL));
/* Projection mode. */
XmxRSetToggleState (pv->menubar, PV_PVIEW_PROJ_PERSPECTIVE,
(WIN_PROJECTION(win) == PERSPECTIVE));
XmxRSetToggleState (pv->menubar, PV_PVIEW_PROJ_ORTHOGRAPHIC,
(WIN_PROJECTION(win) == ORTHOGRAPHIC));
/* Shade mode. */
XmxRSetToggleState (pv->menubar, PV_PVIEW_SHADE_GOURAUD,
(WIN_SHADE(win) == GOURAUD));
XmxRSetToggleState (pv->menubar, PV_PVIEW_SHADE_FLAT,
(WIN_SHADE(win) == FLAT));
/* Lights. */
XmxRSetToggleState (pv->menubar, PV_PVIEW_LIGHT_ONE,
(WIN_LIGHT(win) && FEQ(WIN_LIGHT_X(win), 0.5)));
XmxRSetToggleState (pv->menubar, PV_PVIEW_LIGHT_TWO,
(WIN_LIGHT(win) && FEQ(WIN_LIGHT_X(win), -0.5)));
XmxRSetToggleState (pv->menubar, PV_PVIEW_LIGHT_THREE,
(WIN_LIGHT(win) && FEQ(WIN_LIGHT_X(win), 0.707)));
XmxRSetToggleState (pv->menubar, PV_PVIEW_LIGHT_X,
(WIN_LIGHT(win) && FEQ(WIN_LIGHT_X(win), 1.0) &&
FEQ(WIN_LIGHT_Y(win), 0.0)));
XmxRSetToggleState (pv->menubar, PV_PVIEW_LIGHT_Y,
(WIN_LIGHT(win) && FEQ(WIN_LIGHT_Y(win), 1.0) &&
FEQ(WIN_LIGHT_X(win), 0.0)));
XmxRSetToggleState (pv->menubar, PV_PVIEW_LIGHT_Z,
(WIN_LIGHT(win) && FEQ(WIN_LIGHT_Z(win), 1.0) &&
FEQ(WIN_LIGHT_Y(win), 0.0)));
XmxRSetToggleState (pv->menubar, PV_PVIEW_LIGHT_OFF, (!WIN_LIGHT(win)));
XmxRSetToggleState (pv->menubar, PV_PVIEW_LIGHT_TWOSIDE,
WIN_LIGHT_TWOSIDE(win));
/* Also do dialog adjustments as appropriate. */
return;
}
/* -------------------------- GUIpviewResetProps -------------------------- */
void GUIpviewResetProps (state_t *state, window_t *win)
{
/* For the given polyview window, we reset the gizmos in the
menubar and elsewhere to match props attributes. */
polyview_t *pv;
int value, value2;
assert (win != NULL);
assert (win->type == POLYVIEW);
pv = (polyview_t *)WIN_IMAGE(win);
value = WIN_ROOTOBJINFO(win)->hereonly.value;
value2 = WIN_ROOTOBJINFO(win)->heredown.value;
XmxRSetToggleState (pv->menubar, PV_PROPS_AXES_LARGE,
value & AXESLARGE ? 1 : 0);
XmxRSetToggleState (pv->menubar, PV_PROPS_AXES_SMALL,
value & AXESSMALL ? 1 : 0);
XmxRSetToggleState (pv->menubar, PV_PROPS_AXES_OFF,
!(value & AXESSMALL) && !(value & AXESLARGE) ? 1 : 0);
XmxRSetToggleState (pv->menubar, PV_PROPS_BOX_EDGESFACES,
(value & BOXWIRE) && (value & BOXSHADED) ? 1 : 0);
XmxRSetToggleState (pv->menubar, PV_PROPS_BOX_FACES,
(value & BOXSHADED) && !(value & BOXWIRE) ? 1 : 0);
XmxRSetToggleState (pv->menubar, PV_PROPS_BOX_EDGES,
(value & BOXWIRE) && !(value & BOXSHADED) ? 1 : 0);
XmxRSetToggleState (pv->menubar, PV_PROPS_BOX_OFF,
!(value & BOXWIRE) && !(value & BOXSHADED) ? 1 : 0);
XmxRSetToggleState (pv->menubar, PV_PROPS_GRID_XY,
(value & GRIDXY) ? 1 : 0);
XmxRSetToggleState (pv->menubar, PV_PROPS_GRID_YZ,
(value & GRIDYZ) ? 1 : 0);
XmxRSetToggleState (pv->menubar, PV_PROPS_GRID_XZ,
(value & GRIDXZ) ? 1 : 0);
XmxRSetToggleState (pv->menubar, PV_PROPS_SHADOW_XY,
(value2 & SCATXY) ? 1 : 0);
XmxRSetToggleState (pv->menubar, PV_PROPS_SHADOW_YZ,
(value2 & SCATYZ) ? 1 : 0);
XmxRSetToggleState (pv->menubar, PV_PROPS_SHADOW_XZ,
(value2 & SCATXZ) ? 1 : 0);
XmxRSetToggleState (pv->menubar, PV_PROPS_LEGEND,
win->legend_flag);
XmxRSetToggleState (pv->menubar, PV_PROPS_CREDITS,
win->credits_flag);
/* Also do dialog adjustments as appropriate. */
return;
}
/* ------------------------- GUIpviewResetOutline ------------------------- */
void GUIpviewResetOutline (state_t *state, window_t *win)
{
polyview_t *pv;
int val;
pv = (polyview_t *)WIN_IMAGE(win);
/* Punt if the dialog box hasn't been created yet. */
if (pv->outlineBox == NULL)
return;
val = (int)((float)(WIN_OUTLINE_COLOR(win) & 0x000000ff) / 2.55);
/* Don't ask me... */
if (val > 0 || val < 100)
val++;
PVD (("Adjusting outlinebox scale.\n"));
XmxAdjustScale
(pv->outlineBox->color_scale, val);
PVD (("Done with outline.\n"));
return;
}
/* ------------------------ GUIpviewResetLinewidth ------------------------ */
void GUIpviewResetLinewidth (state_t *state, window_t *win)
{
polyview_t *pv;
int val;
pv = (polyview_t *)WIN_IMAGE(win);
/* Punt if the dialog box hasn't been created yet. */
if (pv->linewidthBox == NULL)
return;
PVD (("Adjusting linewidthbox scale.\n"));
XmxAdjustScale
(pv->linewidthBox->width_scale, win->line_width);
PVD (("Done with linewidth.\n"));
return;
}
/* ------------------------- GUIpviewResetSelect -------------------------- */
void GUIpviewResetSelect (state_t *state, window_t *win)
{
/* For the given polyview window, we reset the gizmos in the
menubar and elsewhere to match pick/select attributes. */
polyview_t *pv;
assert (win != NULL);
assert (win->type == POLYVIEW);
pv = (polyview_t *)WIN_IMAGE(win);
XmxRSetToggleState (pv->menubar, PV_PVIEW_SELECT_VERTICES,
win->pickmode == PICK_VERTEX);
XmxRSetToggleState (pv->menubar, PV_PVIEW_SELECT_FACES,
win->pickmode == PICK_FACE);
XmxRSetToggleState (pv->menubar, PV_PVIEW_SELECT_OBJECTS,
win->pickmode == PICK_OBJECT);
return;
}
/* ------------------------------------------------------------------------ */
/* ---------------------------- LOAD VSET BOX ----------------------------- */
/* ------------------------------------------------------------------------ */
/* ------------------------- GUIloadVsetCallback -------------------------- */
XmxCallback (GUIloadVsetCallback)
{
window_t *win;
polyview_t *pv;
char line[MAXLINELEN];
GUIloadVsetBox *box;
char *fname;
/* Go get the window from the state's window list. */
win = find_window_by_id (gstate, XmxExtractUniqid ((int)client_data));
assert (win != NULL);
/* Make the window active; this won't put an 'activate window'
message in the history list, which is how Polyview 2.0 works. */
if (win != gstate->active_windows)
win_activate (gstate, win);
pv = (polyview_t *)WIN_IMAGE(win);
box = pv->loadVsetBox;
/* Get rid of the dialog first. */
XtUnmanageChild (w);
/* First do axes and color/connect. We do these by hand, and install
commands in the history list to fake the results. */
strcpy (win->vname[PX], XmxTextGetString (box->x_text));
sprintf (line, "data x-axis %s\0", XmxTextGetString (box->x_text));
GUIaddCommand (line);
TRANSaddCommand(gstate, line);
strcpy (win->vname[PY], XmxTextGetString (box->y_text));
sprintf (line, "data y-axis %s\0", XmxTextGetString (box->y_text));
GUIaddCommand (line);
TRANSaddCommand(gstate, line);
strcpy (win->vname[PZ], XmxTextGetString (box->z_text));
sprintf (line, "data z-axis %s\0", XmxTextGetString (box->z_text));
GUIaddCommand (line);
TRANSaddCommand(gstate, line);
strcpy (win->vname[MCONNECT], XmxTextGetString (box->connect_text));
sprintf (line, "data connect %s\0", XmxTextGetString (box->connect_text));
GUIaddCommand (line);
TRANSaddCommand(gstate, line);
strcpy (win->vname[MVSCALAR], XmxTextGetString (box->color_text));
sprintf (line, "data color %s\0", XmxTextGetString (box->color_text));
GUIaddCommand (line);
TRANSaddCommand(gstate, line);
/* Grab the filename. */
fname = (char *)PVMALLOC (128 * sizeof (char));
XmStringGetLtoR
(((XmFileSelectionBoxCallbackStruct *)call_data)->value,
XmSTRING_DEFAULT_CHARSET, &fname);
/* Open the file. */
if ((WIN_SOURCE(win) = find_file (gstate, HDFVSET, fname)) == NULL)
{
/* Error - open dialog box. */
sprintf (line, "File '%s' could not be opened.", fname);
XmxMakeErrorDialog (w, line, "Error While Loading Vset");
XtManageChild (Xmx_w);
goto done;
}
/* The file is open; fake the history list. */
sprintf (line, "data file %s\0", fname);
GUIaddCommand (line);
TRANSaddCommand(gstate, line);
/* Also rename the window here, both win->name and the dialog
title. */
/* This may end up being a problem, since this name change
will not be reflected in the transcript. */
strcpy (win->name, fname);
sprintf (line, "Polyview 3.1: %s", fname);
XmxAdjustDialogTitle (win->base, line);
/* Call data_frame. */
if (data_frame (gstate, win, XmxTextGetString (box->frame_text)) == ST_ERROR)
{
/* Error - open dialog box. */
sprintf (line, "Could not find Vgroup(s) named '%s' in this Vset..",
XmxTextGetString (box->frame_text));
XmxMakeErrorDialog (w, line, "Error While Loading Vset");
XtManageChild (Xmx_w);
goto done;
}
/* data_frame was successful; fake the history list. */
sprintf (line, "data frame %s\0", XmxTextGetString (box->frame_text));
GUIaddCommand (line);
TRANSaddCommand(gstate, line);
/* If we've gotten this far, might as well load the data...? */
parse_line (gstate, "data load", TRUE);
done:
free (fname);
return;
}
/* ------------------------- GUIcreateLoadVsetBox ------------------------- */
GUIloadVsetBox *GUIcreateLoadVsetBox (state_t *state, window_t *win)
{
GUIloadVsetBox *box;
Widget frame;
Widget x_label, y_label, z_label;
Widget connect_label, color_label, frame_label;
Widget sep1;
box = (GUIloadVsetBox *)PVMALLOC (sizeof (GUIloadVsetBox));
/* Set uniqid for dialog box. */
XmxSetUniqid (win->id);
box->base = XmxMakeFileSBDialog
(win->base, "Load Vset", "Enter name of HDF Vset file:",
GUIloadVsetCallback, 0);
/* This makes a form as a work area for the dialog box. */
XmxSetArg (XmNmarginWidth, 5);
XmxSetArg (XmNmarginHeight, 5);
frame = XmxMakeFrame (box->base, XmxShadowEtchedIn);
box->workarea = XmxMakeForm (frame);
x_label = XmxMakeLabel (box->workarea, "X Axis Vdata name:");
XmxSetArg (XmNwidth, 210);
box->x_text = XmxMakeText (box->workarea);
XmxTextSetString (box->x_text, DEF_PXNAME);
y_label = XmxMakeLabel (box->workarea, "Y Axis Vdata name:");
XmxSetArg (XmNwidth, 210);
box->y_text = XmxMakeText (box->workarea);
XmxTextSetString (box->y_text, DEF_PYNAME);
z_label = XmxMakeLabel (box->workarea, "Z Axis Vdata name:");
XmxSetArg (XmNwidth, 210);
box->z_text = XmxMakeText (box->workarea);
XmxTextSetString (box->z_text, DEF_PZNAME);
connect_label = XmxMakeLabel (box->workarea, "Connectivity Vdata name:");
XmxSetArg (XmNwidth, 210);
box->connect_text = XmxMakeText (box->workarea);
XmxTextSetString (box->connect_text, DEF_CONNECTNAME);
color_label = XmxMakeLabel (box->workarea, "Color Vdata name:");
XmxSetArg (XmNwidth, 210);
box->color_text = XmxMakeText (box->workarea);
XmxTextSetString (box->color_text, DEF_VSCALARNAME);
sep1 = XmxMakeHorizontalSeparator (box->workarea);
frame_label = XmxMakeLabel (box->workarea, "Frames to load:");
XmxSetArg (XmNwidth, 210);
box->frame_text = XmxMakeText (box->workarea);
XmxTextSetString (box->frame_text, DEF_GROUPNAME);
/* Constraints for box->workarea. */
XmxSetConstraints
(x_label, XmATTACH_FORM, XmATTACH_NONE, XmATTACH_FORM, XmATTACH_NONE,
NULL, NULL, NULL, NULL);
XmxSetConstraints
(box->x_text, XmATTACH_FORM, XmATTACH_NONE, XmATTACH_NONE, XmATTACH_FORM,
NULL, NULL, NULL, NULL);
XmxSetConstraints
(y_label, XmATTACH_WIDGET, XmATTACH_NONE, XmATTACH_FORM, XmATTACH_NONE,
box->x_text, NULL, NULL, NULL);
XmxSetConstraints
(box->y_text, XmATTACH_WIDGET, XmATTACH_NONE, XmATTACH_NONE, XmATTACH_FORM,
box->x_text, NULL, NULL, NULL);
XmxSetConstraints
(z_label, XmATTACH_WIDGET, XmATTACH_NONE, XmATTACH_FORM, XmATTACH_NONE,
box->y_text, NULL, NULL, NULL);
XmxSetConstraints
(box->z_text, XmATTACH_WIDGET, XmATTACH_NONE, XmATTACH_NONE, XmATTACH_FORM,
box->y_text, NULL, NULL, NULL);
XmxSetConstraints
(connect_label, XmATTACH_WIDGET, XmATTACH_NONE, XmATTACH_FORM,
XmATTACH_NONE, box->z_text, NULL, NULL, NULL);
XmxSetConstraints
(box->connect_text, XmATTACH_WIDGET, XmATTACH_NONE, XmATTACH_NONE,
XmATTACH_FORM, box->z_text, NULL, NULL, NULL);
XmxSetConstraints
(color_label, XmATTACH_WIDGET, XmATTACH_NONE, XmATTACH_FORM,
XmATTACH_NONE, box->connect_text, NULL, NULL, NULL);
XmxSetConstraints
(box->color_text, XmATTACH_WIDGET, XmATTACH_NONE, XmATTACH_NONE,
XmATTACH_FORM, box->connect_text, NULL, NULL, NULL);
XmxSetConstraints
(sep1, XmATTACH_WIDGET, XmATTACH_WIDGET, XmATTACH_FORM, XmATTACH_FORM,
box->color_text, box->frame_text, NULL, NULL);
XmxSetConstraints
(frame_label, XmATTACH_NONE, XmATTACH_FORM, XmATTACH_FORM, XmATTACH_NONE,
NULL, NULL, NULL, NULL);
XmxSetConstraints
(box->frame_text, XmATTACH_NONE, XmATTACH_FORM, XmATTACH_NONE,
XmATTACH_FORM, NULL, NULL, NULL, NULL);
XmxZeroUniqid ();
/* Dialog will be managed in the calling routine. */
return box;
}
/* ------------------------------------------------------------------------ */
/* -------------------------- OUTLINE COLOR BOX --------------------------- */
/* ------------------------------------------------------------------------ */
static XmxCallback (GUIcolorScaleCB)
{
window_t *win;
char line[MAXLINELEN];
int val = ((XmScaleCallbackStruct *)call_data)->value, c;
float col;
/* Go get the window from the state's window list. */
win = find_window_by_id (gstate, XmxExtractUniqid ((int)client_data));
assert (win != NULL);
if (WIN_DRAW(win) != draw_outlined_faces)
{
/* We're not drawing outlined faces yet, so let someone
else do the work. */
sprintf (line, "draw outlined %f", (float)val * 0.01);
parse_line (gstate, line, TRUE);
}
else
{
/* We are drawing outlined faces already, so do it fast. */
c = (int)((float)val * 2.55);
if (c != (WIN_OUTLINE_COLOR(win) & 0x000000ff))
{
PLAYAFILE ("/usr/lib/sounds/prosonus/instr/woodblock.aiff");
WIN_OUTLINE_COLOR(win) = c + (c << 8) + (c << 16);
set_redraw (gstate, win);
sprintf (line, "draw outlined %0.2f", (float)val * 0.01);
GUIaddCommand (line);
TRANSaddCommand(gstate, line);
}
}
return;
}
static XmxCallback (GUIcolorOKButtonCB)
{
window_t *win;
polyview_t *pv;
/* Go get the window from the state's window list. */
win = find_window_by_id (gstate, XmxExtractUniqid ((int)client_data));
assert (win != NULL);
pv = (polyview_t *)WIN_IMAGE(win);
XtUnmanageChild (pv->outlineBox->base);
return;
}
GUIoutlineBox *GUIcreateOutlineBox (state_t *state, window_t *win)
{
GUIoutlineBox *box;
Widget dialog_frame, control_form, color_label;
Widget dialog_sep, buttons_form;
box = (GUIoutlineBox *)PVMALLOC (sizeof (GUIoutlineBox));
/* Dialog will have same uniqid as polyview window. */
XmxSetUniqid (win->id);
/* Set up dialog. */
box->base = XmxMakeFormDialog (win->base, "Outline Color");
dialog_frame = XmxMakeFrame (box->base, XmxShadowOut);
XmxSetConstraints
(dialog_frame, XmATTACH_FORM, XmATTACH_FORM, XmATTACH_FORM, XmATTACH_FORM,
NULL, NULL, NULL, NULL);
/* Main control form. */
XmxSetArg (XmNhorizontalSpacing, 10);
control_form = XmxMakeForm (dialog_frame);
/* Label and slider. */
color_label = XmxMakeLabel (control_form, "Outline Color:");
XmxSetArg (XmNwidth, 250);
box->color_scale = XmxMakeScale
(control_form, GUIcolorScaleCB, 0, NULL, 0, 100,
(int) (((float)win->outline_color / (float)0xffffff) * 100.0), 2);
/* Separator and buttons for dialog box. */
dialog_sep = XmxMakeHorizontalSeparator (control_form);
buttons_form = XmxMakeFormAndOneButton
(control_form, GUIcolorOKButtonCB, "OK", 0);
/* Constraints for control_form. */
XmxSetArg (XmNtopOffset, 10);
XmxSetConstraints
(color_label, XmATTACH_FORM, XmATTACH_NONE, XmATTACH_FORM, XmATTACH_NONE,
NULL, NULL, NULL, NULL);
XmxSetArg (XmNbottomOffset, 10);
XmxSetConstraints
(box->color_scale, XmATTACH_WIDGET, XmATTACH_NONE, XmATTACH_FORM,
XmATTACH_FORM, color_label, NULL, NULL, NULL);
XmxSetArg (XmNtopOffset, 10);
XmxSetConstraints
(dialog_sep, XmATTACH_WIDGET, XmATTACH_WIDGET, XmATTACH_FORM,
XmATTACH_FORM, box->color_scale, buttons_form, NULL, NULL);
XmxSetConstraints
(buttons_form, XmATTACH_NONE, XmATTACH_FORM, XmATTACH_FORM, XmATTACH_FORM,
NULL, NULL, NULL, NULL);
return box;
}
/* ------------------------------------------------------------------------ */
/* ---------------------------- LINEWIDTH BOX ----------------------------- */
/* ------------------------------------------------------------------------ */
static XmxCallback (GUIwidthScaleCB)
{
window_t *win;
char line[MAXLINELEN];
int val = ((XmScaleCallbackStruct *)call_data)->value;
/* Go get the window from the state's window list. */
win = find_window_by_id (gstate, XmxExtractUniqid ((int)client_data));
assert (win != NULL);
if (val != win->line_width)
{
PLAYAFILE ("/usr/lib/sounds/prosonus/instr/woodblock.aiff");
win->line_width = val;
set_redraw (gstate, win);
sprintf (line, "draw linewidth %d", val);
GUIaddCommand (line);
TRANSaddCommand(gstate, line);
}
return;
}
static XmxCallback (GUIwidthOKButtonCB)
{
window_t *win;
polyview_t *pv;
/* Go get the window from the state's window list. */
win = find_window_by_id (gstate, XmxExtractUniqid ((int)client_data));
assert (win != NULL);
pv = (polyview_t *)WIN_IMAGE(win);
XtUnmanageChild (pv->linewidthBox->base);
return;
}
GUIlinewidthBox *GUIcreateLinewidthBox (state_t *state, window_t *win)
{
GUIlinewidthBox *box;
Widget dialog_frame, control_form, width_label;
Widget dialog_sep, buttons_form;
box = (GUIlinewidthBox *)PVMALLOC (sizeof (GUIlinewidthBox));
/* Dialog will have same uniqid as polyview window. */
XmxSetUniqid (win->id);
/* Set up dialog. */
box->base = XmxMakeFormDialog (win->base, "Linewidth Control");
dialog_frame = XmxMakeFrame (box->base, XmxShadowOut);
XmxSetConstraints
(dialog_frame, XmATTACH_FORM, XmATTACH_FORM, XmATTACH_FORM, XmATTACH_FORM,
NULL, NULL, NULL, NULL);
/* Main control form. */
XmxSetArg (XmNhorizontalSpacing, 10);
control_form = XmxMakeForm (dialog_frame);
/* Label and slider. */
width_label = XmxMakeLabel (control_form, "Linewidth:");
XmxSetArg (XmNwidth, 250);
box->width_scale = XmxMakeScale
(control_form, GUIwidthScaleCB, 0, NULL, 1, 10, win->line_width, 0);
/* Separator and buttons for dialog box. */
dialog_sep = XmxMakeHorizontalSeparator (control_form);
buttons_form = XmxMakeFormAndOneButton
(control_form, GUIwidthOKButtonCB, "OK", 0);
/* Constraints for control_form. */
XmxSetArg (XmNtopOffset, 10);
XmxSetConstraints
(width_label, XmATTACH_FORM, XmATTACH_NONE, XmATTACH_FORM, XmATTACH_NONE,
NULL, NULL, NULL, NULL);
XmxSetArg (XmNbottomOffset, 10);
XmxSetConstraints
(box->width_scale, XmATTACH_WIDGET, XmATTACH_NONE, XmATTACH_FORM,
XmATTACH_FORM, width_label, NULL, NULL, NULL);
XmxSetArg (XmNtopOffset, 10);
XmxSetConstraints
(dialog_sep, XmATTACH_WIDGET, XmATTACH_WIDGET, XmATTACH_FORM,
XmATTACH_FORM, box->width_scale, buttons_form, NULL, NULL);
XmxSetConstraints
(buttons_form, XmATTACH_NONE, XmATTACH_FORM, XmATTACH_FORM, XmATTACH_FORM,
NULL, NULL, NULL, NULL);
return box;
}
/* ------------------------------------------------------------------------ */
/* ------------------------------ SPHERE BOX ------------------------------ */
/* ------------------------------------------------------------------------ */
static XmxCallback (GUIsphereOKButtonCB)
{
window_t *win;
polyview_t *pv;
char *value, *sptr;
float sphereSize;
/* Go get the window from the state's window list. */
win = find_window_by_id (gstate, XmxExtractUniqid ((int)client_data));
assert (win != NULL);
pv = (polyview_t *)WIN_IMAGE(win);
XtUnmanageChild (pv->sphereBox->base);
value = XmxTextGetString(pv->sphereBox->size_text);
sphereSize = (float)strtod(value, &sptr);
if (sptr != value &&
win->sphere_size != sphereSize) {
char line[MAXLINELEN];
sprintf (line, "sphere size %f", sphereSize);
parse_line (gstate, line, TRUE);
}
XtFree(value);
return;
}
void GUIpviewResetSphere (state_t *state, window_t *win)
{
polyview_t *pv;
int val;
char line[MAXLINELEN];
pv = (polyview_t *)WIN_IMAGE(win);
/* Punt if the dialog box hasn't been created yet. */
if (pv->sphereBox == NULL)
return;
/* Do yer stuff. */
/* Who'd wanna go higher than 10? */
if (win->sphere_depth <= 10)
XmxAdjustScale (pv->sphereBox->depth_scale, win->sphere_depth);
else
XmxAdjustScale (pv->sphereBox->depth_scale, 10);
sprintf (line, "%1.3f", win->sphere_size);
XmxTextSetString (pv->sphereBox->size_text, line);
return;
}
static XmxCallback (GUIspheredepthScaleCB)
{
window_t *win;
char line[MAXLINELEN];
int val = ((XmScaleCallbackStruct *)call_data)->value;
/* Go get the window from the state's window list. */
win = find_window_by_id (gstate, XmxExtractUniqid ((int)client_data));
assert (win != NULL);
/* Beeeeeeee smart. */
if (val != win->sphere_depth)
{
PLAYAFILE ("/usr/lib/sounds/prosonus/instr/woodblock.aiff");
win->sphere_depth = val;
set_redraw (gstate, win);
sprintf (line, "sphere depth %d", val);
GUIaddCommand (line);
TRANSaddCommand(gstate, line);
}
return;
}
static XmxCallback (GUIspheresizeTextCB)
{
char line[MAXLINELEN];
float val;
int rc;
rc = sscanf (XmxTextGetString (w), "%f", &val);
if (rc == 1)
{
/* Got our value. */
sprintf (line, "sphere size %f", val);
parse_line (gstate, line, TRUE);
}
return;
}
GUIsphereBox *GUIcreateSphereBox (state_t *state, window_t *win)
{
GUIsphereBox *box;
Widget dialog_frame, control_form, size_label, depth_label;
Widget mid_sep;
Widget dialog_sep, buttons_form;
char line[MAXLINELEN];
box = (GUIsphereBox *)PVMALLOC (sizeof (GUIsphereBox));
/* Dialog will have same uniqid as polyview window. */
XmxSetUniqid (win->id);
/* Set up dialog. */
box->base = XmxMakeFormDialog (win->base, "Sphere Control");
dialog_frame = XmxMakeFrame (box->base, XmxShadowOut);
XmxSetConstraints
(dialog_frame, XmATTACH_FORM, XmATTACH_FORM, XmATTACH_FORM, XmATTACH_FORM,
NULL, NULL, NULL, NULL);
/* Main control form. */
XmxSetArg (XmNhorizontalSpacing, 10);
control_form = XmxMakeForm (dialog_frame);
/* Label and slider. */
size_label = XmxMakeLabel (control_form, "Sphere Size:");
XmxSetArg (XmNcolumns, 15);
box->size_text = XmxMakeText (control_form);
XmxAddCallbackToText (box->size_text, GUIspheresizeTextCB, 0);
sprintf (line, "%1.3f", win->sphere_size);
XmxTextSetString (box->size_text, line);
mid_sep = XmxMakeHorizontalSeparator (control_form);
depth_label = XmxMakeLabel (control_form, "Sphere Depth:");
XmxSetArg (XmNwidth, 250);
box->depth_scale = XmxMakeScale
(control_form, GUIspheredepthScaleCB, 0, NULL, 1, 10,
win->sphere_depth, 0);
/* Separator and buttons for dialog box. */
dialog_sep = XmxMakeHorizontalSeparator (control_form);
buttons_form = XmxMakeFormAndOneButton
(control_form, GUIsphereOKButtonCB, "OK", 0);
/* Constraints for control_form. */
XmxSetArg (XmNtopOffset, 10);
XmxSetConstraints
(size_label, XmATTACH_FORM, XmATTACH_NONE, XmATTACH_FORM, XmATTACH_NONE,
NULL, NULL, NULL, NULL);
XmxSetArg (XmNtopOffset, 10);
XmxSetConstraints
(box->size_text, XmATTACH_FORM, XmATTACH_NONE,
XmATTACH_NONE, XmATTACH_FORM,
NULL, NULL, NULL, NULL);
XmxSetArg (XmNtopOffset, 10);
XmxSetConstraints
(mid_sep, XmATTACH_WIDGET, XmATTACH_NONE, XmATTACH_FORM, XmATTACH_FORM,
box->size_text, NULL, NULL, NULL);
XmxSetConstraints
(depth_label, XmATTACH_WIDGET, XmATTACH_NONE, XmATTACH_FORM, XmATTACH_NONE,
mid_sep, NULL, NULL, NULL);
XmxSetArg (XmNbottomOffset, 10);
XmxSetConstraints
(box->depth_scale, XmATTACH_WIDGET, XmATTACH_NONE, XmATTACH_FORM,
XmATTACH_FORM, depth_label, NULL, NULL, NULL);
XmxSetArg (XmNtopOffset, 10);
XmxSetConstraints
(dialog_sep, XmATTACH_WIDGET, XmATTACH_WIDGET, XmATTACH_FORM,
XmATTACH_FORM, box->depth_scale, buttons_form, NULL, NULL);
XmxSetConstraints
(buttons_form, XmATTACH_NONE, XmATTACH_FORM, XmATTACH_FORM, XmATTACH_FORM,
NULL, NULL, NULL, NULL);
return box;
}
/* ------------------------------------------------------------------------ */
/* --------------------------- MENUBAR CALLBACK --------------------------- */
/* ------------------------------------------------------------------------ */
static XmxCallback (GUIrayBoxCB)
{
char *fname;
char line[MAXLINELEN];
PLAYAFILE ("/usr/lib/sounds/prosonus/sfx/tennis.aiff");
fname = (char *)PVMALLOC (128 * sizeof (char));
XmStringGetLtoR (((XmFileSelectionBoxCallbackStruct *)call_data)->value,
XmSTRING_DEFAULT_CHARSET,
&fname);
sprintf (line, "save ray %s\0", fname);
parse_line (gstate, line, TRUE);
free (fname);
XtUnmanageChild (w);
return;
}
static XmxCallback (GUIrgbBoxCB)
{
char *fname;
char line[MAXLINELEN];
XtUnmanageChild (w);
XSync(XtDisplay(w),False);
PLAYAFILE ("/usr/lib/sounds/prosonus/sfx/tennis.aiff");
fname = (char *)PVMALLOC (128 * sizeof (char));
XmStringGetLtoR (((XmFileSelectionBoxCallbackStruct *)call_data)->value,
XmSTRING_DEFAULT_CHARSET,
&fname);
sprintf (line, "save rgb %s", fname);
sleep(1);
parse_line (gstate, line, TRUE);
free (fname);
return;
}
#ifdef RENDERMAN
static XmxCallback (GUIrmBoxCB)
{
char *fname;
char line[MAXLINELEN];
PLAYAFILE ("/usr/lib/sounds/prosonus/sfx/tennis.aiff");
fname = (char *)PVMALLOC (128 * sizeof (char));
XmStringGetLtoR (((XmFileSelectionBoxCallbackStruct *)call_data)->value,
XmSTRING_DEFAULT_CHARSET,
&fname);
sprintf (line, "save renderman %s\0", fname);
parse_line (gstate, line, TRUE);
free (fname);
XtUnmanageChild (w);
return;
}
#endif /* RENDERMAN */
static char *timeout_str;
static XmxCallback (GUIhdfTimeout)
{
parse_line (gstate, timeout_str, TRUE);
return;
}
static XmxCallback (GUIhdfBoxCB)
{
char *fname;
static char line[MAXLINELEN];
PLAYAFILE ("/usr/lib/sounds/prosonus/sfx/tennis.aiff");
XtUnmanageChild (w);
set_redraw
(gstate, find_window_by_id (gstate, XmxExtractUniqid ((int)client_data)));
redraw_windows (gstate);
fname = (char *)PVMALLOC (128 * sizeof (char));
XmStringGetLtoR (((XmFileSelectionBoxCallbackStruct *)call_data)->value,
XmSTRING_DEFAULT_CHARSET,
&fname);
sprintf (line, "save image %s\0", fname);
timeout_str = line;
free (fname);
/* Since the box doesn't go away until we've reentered the main loop,
make sure we come back and actually issue the save image
command. Boy, Motif is fun. */
XtAppAddTimeOut (gstate->app_context, 1000, GUIhdfTimeout, True);
return;
}
XmxCallback (GUIpolyviewMenubarCB)
{
window_t *win;
polyview_t *pv;
char line[MAXLINELEN];
/* Go get the window from the state's window list. */
win = find_window_by_id (gstate, XmxExtractUniqid ((int)client_data));
assert (win != NULL);
/* Make the window active; this won't put an 'activate window'
message in the history list, which is how Polyview 2.0 works. */
if (win != gstate->active_windows)
win_activate (gstate, win);
pv = (polyview_t *)WIN_IMAGE(win);
switch (XmxExtractToken ((int)client_data))
{
case PV_PVIEW_LOAD_VSET:
PLAYAFILE ("/usr/lib/sounds/prosonus/musictags/slinky_slap.aiff");
if (pv->loadVsetBox == NULL)
pv->loadVsetBox = GUIcreateLoadVsetBox (gstate, win);
else
XmFileSelectionDoSearch (pv->loadVsetBox->base, NULL);
XmxManageRemanage (pv->loadVsetBox->base);
break;
case PV_PVIEW_DTM_SEND:
parse_line (gstate, "dtm send", TRUE);
break;
case PV_PVIEW_DATA_LOAD:
parse_line (gstate, "data load", TRUE);
break;
case PV_PVIEW_DATA_NORMALIZE:
parse_line (gstate, "data normalize", TRUE);
break;
case PV_PVIEW_SAVE_RAY:
if (pv->ray_box == NULL)
{
XmxSetUniqid (XmxExtractUniqid ((int)client_data));
pv->ray_box = XmxMakeFileSBDialog
(win->base, "Save Rayshade File",
"Enter filename for Rayshade file:",
GUIrayBoxCB, 0);
}
else
XmFileSelectionDoSearch (pv->ray_box, NULL);
XmxManageRemanage (pv->ray_box);
break;
case PV_PVIEW_SAVE_RGB:
if (pv->rgb_box == NULL)
{
XmxSetUniqid (XmxExtractUniqid ((int)client_data));
pv->rgb_box = XmxMakeFileSBDialog
(win->base, "Save RGB File",
"Enter filename for RGB file:",
GUIrgbBoxCB, 0);
}
else
XmFileSelectionDoSearch (pv->rgb_box, NULL);
XmxManageRemanage (pv->rgb_box);
break;
#ifdef RENDERMAN
case PV_PVIEW_SAVE_RENDERMAN:
if (pv->rm_box == NULL)
{
XmxSetUniqid (XmxExtractUniqid ((int)client_data));
pv->rm_box = XmxMakeFileSBDialog
(win->base, "Save Renderman File",
"Enter filename for Renderman file:",
GUIrmBoxCB, 0);
}
else
XmFileSelectionDoSearch (pv->rm_box, NULL);
XmxManageRemanage (pv->rm_box);
break;
#endif /* RENDERMAN */
case PV_PVIEW_SAVE_HDF:
if (pv->hdf_box == NULL)
{
XmxSetUniqid (XmxExtractUniqid ((int)client_data));
pv->hdf_box = XmxMakeFileSBDialog
(win->base, "Save HDF Image",
"Enter filename for HDF image:",
GUIhdfBoxCB, 0);
}
else
XmFileSelectionDoSearch (pv->hdf_box, NULL);
XmxManageRemanage (pv->hdf_box);
break;
case PV_PVIEW_RESET:
PLAYAFILE ("/usr/lib/sounds/prosonus/sfx/tennis.aiff");
parse_line (gstate, "reset", TRUE);
break;
case PV_PVIEW_CLOSE_WINDOW:
/* NO! This should close by id but fake the history list.
Compromise between script shit and interactive use -- interactive
integrity is more important than super-flexible scripts. */
sprintf (line, "window close polyview \"%s\"", win->name);
parse_line (gstate, line, TRUE);
break;
case PV_PROPS_FOCUS:
PLAYAFILE ("/usr/lib/sounds/prosonus/sfx/click2.aiff");
parse_line (gstate, "props focus toggle", TRUE);
break;
case PV_PVIEW_TIME_FORWARD:
PLAYAFILE ("/usr/lib/sounds/prosonus/instr/braz_hi_shaker.aiff");
parse_line (gstate, "time forward", TRUE);
break;
case PV_PVIEW_TIME_FORWARDSTEP:
PLAYAFILE ("/usr/lib/sounds/prosonus/instr/drm_clave.aiff");
parse_line (gstate, "time forward step", TRUE);
break;
case PV_PVIEW_TIME_STOP:
PLAYAFILE ("/usr/lib/sounds/prosonus/instr/tama_base_drm.aiff");
parse_line (gstate, "time stop", TRUE);
break;
case PV_PVIEW_TIME_REVERSESTEP:
PLAYAFILE ("/usr/lib/sounds/prosonus/instr/drm_clave.aiff");
parse_line (gstate, "time reverse step", TRUE);
break;
case PV_PVIEW_TIME_REVERSE:
PLAYAFILE ("/usr/lib/sounds/prosonus/instr/braz_hi_shaker.aiff");
parse_line (gstate, "time reverse", TRUE);
break;
case PV_PVIEW_TIME_RESET:
PLAYAFILE ("/usr/lib/sounds/prosonus/sfx/tennis.aiff");
parse_line (gstate, "time reset", TRUE);
break;
case PV_PVIEW_DRAW_VERTICES:
PLAYAFILE ("/usr/lib/sounds/prosonus/sfx/door_slam.aiff");
parse_line (gstate, "draw vertices", TRUE);
break;
case PV_PVIEW_DRAW_EDGES:
PLAYAFILE ("/usr/lib/sounds/prosonus/sfx/door_slam.aiff");
parse_line (gstate, "draw edges", TRUE);
break;
case PV_PVIEW_DRAW_HIDDEN:
PLAYAFILE ("/usr/lib/sounds/prosonus/sfx/door_slam.aiff");
parse_line (gstate, "draw hidden", TRUE);
break;
case PV_PVIEW_DRAW_FACES:
PLAYAFILE ("/usr/lib/sounds/prosonus/sfx/door_slam.aiff");
parse_line (gstate, "draw faces", TRUE);
break;
case PV_PVIEW_DRAW_OUTFACES:
PLAYAFILE ("/usr/lib/sounds/prosonus/sfx/door_slam.aiff");
parse_line (gstate, "draw outlined", TRUE);
break;
case PV_PVIEW_DRAG_NOTHING:
PLAYAFILE ("/usr/lib/sounds/prosonus/sfx/door_slam.aiff");
parse_line (gstate, "drag nothing", TRUE);
break;
case PV_PVIEW_DRAG_BOX:
PLAYAFILE ("/usr/lib/sounds/prosonus/sfx/door_slam.aiff");
parse_line (gstate, "drag box", TRUE);
break;
case PV_PVIEW_DRAG_VERTICES:
PLAYAFILE ("/usr/lib/sounds/prosonus/sfx/door_slam.aiff");
parse_line (gstate, "drag vertices", TRUE);
break;
case PV_PVIEW_DRAG_EDGES:
PLAYAFILE ("/usr/lib/sounds/prosonus/sfx/door_slam.aiff");
parse_line (gstate, "drag edges", TRUE);
break;
case PV_PVIEW_DRAG_HIDDEN:
PLAYAFILE ("/usr/lib/sounds/prosonus/sfx/door_slam.aiff");
parse_line (gstate, "drag hidden", TRUE);
break;
case PV_PVIEW_DRAG_FACES:
PLAYAFILE ("/usr/lib/sounds/prosonus/sfx/door_slam.aiff");
parse_line (gstate, "drag faces", TRUE);
break;
case PV_PVIEW_DRAG_OUTFACES:
PLAYAFILE ("/usr/lib/sounds/prosonus/sfx/door_slam.aiff");
parse_line (gstate, "drag outlined", TRUE);
break;
case PV_PVIEW_DRAG_SAMEASDRAW:
PLAYAFILE ("/usr/lib/sounds/prosonus/sfx/door_slam.aiff");
parse_line (gstate, "drag same_as_draw", TRUE);
break;
case PV_PVIEW_PROJ_PERSPECTIVE:
PLAYAFILE ("/usr/lib/sounds/prosonus/sfx/door_slam.aiff");
parse_line (gstate, "draw perspective", TRUE);
break;
case PV_PVIEW_PROJ_ORTHOGRAPHIC:
PLAYAFILE ("/usr/lib/sounds/prosonus/sfx/door_slam.aiff");
parse_line (gstate, "draw orthographic", TRUE);
break;
case PV_PVIEW_SHADE_GOURAUD:
PLAYAFILE ("/usr/lib/sounds/prosonus/sfx/door_slam.aiff");
parse_line (gstate, "draw gouraud", TRUE);
break;
case PV_PVIEW_SHADE_FLAT:
PLAYAFILE ("/usr/lib/sounds/prosonus/sfx/door_slam.aiff");
parse_line (gstate, "draw flat", TRUE);
break;
case PV_PVIEW_LIGHT_ONE:
PLAYAFILE ("/usr/lib/sounds/prosonus/sfx/door_slam.aiff");
parse_line (gstate, "light one", TRUE);
break;
case PV_PVIEW_LIGHT_TWO:
PLAYAFILE ("/usr/lib/sounds/prosonus/sfx/door_slam.aiff");
parse_line (gstate, "light two", TRUE);
break;
case PV_PVIEW_LIGHT_THREE:
PLAYAFILE ("/usr/lib/sounds/prosonus/sfx/door_slam.aiff");
parse_line (gstate, "light three", TRUE);
break;
case PV_PVIEW_LIGHT_X:
PLAYAFILE ("/usr/lib/sounds/prosonus/sfx/door_slam.aiff");
parse_line (gstate, "light x", TRUE);
break;
case PV_PVIEW_LIGHT_Y:
PLAYAFILE ("/usr/lib/sounds/prosonus/sfx/door_slam.aiff");
parse_line (gstate, "light y", TRUE);
break;
case PV_PVIEW_LIGHT_Z:
PLAYAFILE ("/usr/lib/sounds/prosonus/sfx/door_slam.aiff");
parse_line (gstate, "light z", TRUE);
break;
case PV_PVIEW_LIGHT_OFF:
PLAYAFILE ("/usr/lib/sounds/prosonus/sfx/door_slam.aiff");
parse_line (gstate, "light off", TRUE);
break;
case PV_PVIEW_LIGHT_TWOSIDE:
PLAYAFILE ("/usr/lib/sounds/prosonus/sfx/click2.aiff");
(((XmToggleButtonCallbackStruct *)(call_data))->set) ?
parse_line (gstate, "light twoside on", TRUE) :
parse_line (gstate, "light twoside off", TRUE);
break;
case PV_PROPS_AXES_SMALL:
PLAYAFILE ("/usr/lib/sounds/prosonus/sfx/door_slam.aiff");
parse_line (gstate, "props axes small", TRUE);
break;
case PV_PROPS_AXES_LARGE:
PLAYAFILE ("/usr/lib/sounds/prosonus/sfx/door_slam.aiff");
parse_line (gstate, "props axes large", TRUE);
break;
case PV_PROPS_AXES_OFF:
PLAYAFILE ("/usr/lib/sounds/prosonus/sfx/door_slam.aiff");
parse_line (gstate, "props axes off", TRUE);
break;
case PV_PROPS_BOX_EDGESFACES:
PLAYAFILE ("/usr/lib/sounds/prosonus/sfx/door_slam.aiff");
parse_line (gstate, "props box all", TRUE);
break;
case PV_PROPS_BOX_FACES:
PLAYAFILE ("/usr/lib/sounds/prosonus/sfx/click2.aiff");
parse_line (gstate, "props box faces", TRUE);
break;
case PV_PROPS_BOX_EDGES:
PLAYAFILE ("/usr/lib/sounds/prosonus/sfx/click2.aiff");
parse_line (gstate, "props box edges", TRUE);
break;
case PV_PROPS_BOX_OFF:
PLAYAFILE ("/usr/lib/sounds/prosonus/sfx/door_slam.aiff");
parse_line (gstate, "props box off", TRUE);
break;
case PV_PROPS_GRID_ALL:
PLAYAFILE ("/usr/lib/sounds/prosonus/sfx/door_slam.aiff");
parse_line (gstate, "props grid all", TRUE);
break;
case PV_PROPS_GRID_XY:
PLAYAFILE ("/usr/lib/sounds/prosonus/sfx/click2.aiff");
parse_line (gstate, "props grid xy", TRUE);
break;
case PV_PROPS_GRID_YZ:
PLAYAFILE ("/usr/lib/sounds/prosonus/sfx/click2.aiff");
parse_line (gstate, "props grid yz", TRUE);
break;
case PV_PROPS_GRID_XZ:
PLAYAFILE ("/usr/lib/sounds/prosonus/sfx/click2.aiff");
parse_line (gstate, "props grid xz", TRUE);
break;
case PV_PROPS_GRID_OFF:
PLAYAFILE ("/usr/lib/sounds/prosonus/sfx/door_slam.aiff");
parse_line (gstate, "props grid off", TRUE);
break;
case PV_PROPS_SHADOW_ALL:
PLAYAFILE ("/usr/lib/sounds/prosonus/sfx/door_slam.aiff");
parse_line (gstate, "props shadow all", TRUE);
break;
case PV_PROPS_SHADOW_XY:
PLAYAFILE ("/usr/lib/sounds/prosonus/sfx/click2.aiff");
parse_line (gstate, "props shadow xy", TRUE);
break;
case PV_PROPS_SHADOW_YZ:
PLAYAFILE ("/usr/lib/sounds/prosonus/sfx/click2.aiff");
parse_line (gstate, "props shadow yz", TRUE);
break;
case PV_PROPS_SHADOW_XZ:
PLAYAFILE ("/usr/lib/sounds/prosonus/sfx/click2.aiff");
parse_line (gstate, "props shadow xz", TRUE);
break;
case PV_PROPS_SHADOW_OFF:
PLAYAFILE ("/usr/lib/sounds/prosonus/sfx/door_slam.aiff");
parse_line (gstate, "props shadow off", TRUE);
break;
case PV_PROPS_LEGEND:
PLAYAFILE ("/usr/lib/sounds/prosonus/sfx/click2.aiff");
(((XmToggleButtonCallbackStruct *)(call_data))->set) ?
parse_line (gstate, "props legend on", TRUE) :
parse_line (gstate, "props legend off", TRUE);
break;
case PV_PROPS_CREDITS:
PLAYAFILE ("/usr/lib/sounds/prosonus/sfx/click2.aiff");
(((XmToggleButtonCallbackStruct *)(call_data))->set) ?
parse_line (gstate, "props credits on", TRUE) :
parse_line (gstate, "props credits off", TRUE);
break;
case PV_PROPS_ALL_OFF:
PLAYAFILE ("/usr/lib/sounds/prosonus/sfx/tennis.aiff");
parse_line (gstate, "props all off", TRUE);
break;
case PV_PVIEW_SELECT_VERTICES:
PLAYAFILE ("/usr/lib/sounds/prosonus/sfx/door_slam.aiff");
parse_line (gstate, "select vertices", TRUE);
break;
case PV_PVIEW_SELECT_FACES:
PLAYAFILE ("/usr/lib/sounds/prosonus/sfx/door_slam.aiff");
parse_line (gstate, "select faces", TRUE);
break;
case PV_PVIEW_SELECT_OBJECTS:
PLAYAFILE ("/usr/lib/sounds/prosonus/sfx/door_slam.aiff");
parse_line (gstate, "select objects", TRUE);
break;
case PV_PVIEW_SELECT_ALL:
PLAYAFILE ("/usr/lib/sounds/prosonus/sfx/tennis.aiff");
parse_line (gstate, "select all", TRUE);
break;
case PV_PVIEW_POPUP_OUTLINE:
if (pv->outlineBox == NULL)
pv->outlineBox = GUIcreateOutlineBox (gstate, win);
XmxManageRemanage (pv->outlineBox->base);
break;
case PV_PVIEW_POPUP_LINEWIDTH:
if (pv->linewidthBox == NULL)
pv->linewidthBox = GUIcreateLinewidthBox (gstate, win);
XmxManageRemanage (pv->linewidthBox->base);
break;
case PV_PVIEW_POPUP_SPHERE:
if (pv->sphereBox == NULL)
pv->sphereBox = GUIcreateSphereBox (gstate, win);
XmxManageRemanage (pv->sphereBox->base);
break;
case PV_PVIEW_HELP_ONWINDOW:
GUIdoHelp (PV_PVIEW_HELP_ONWINDOW);
#if 0
XmUpdateDisplay (gstate->base);
PLAYAFILE ("pvpoly.aiff");
#endif
break;
}
return;
}
/* ------------------------- GUIpolyviewWindowCB -------------------------- */
XmxCallback (GUIpolyviewWindowCB)
{
window_t *win;
polyview_t *pv;
/* Go get the window from the state's window list. */
win = find_window_by_id (gstate, XmxExtractUniqid ((int)client_data));
assert (win != NULL);
/* Make the window active; this won't put an 'activate window'
message in the history list, which is how Polyview 2.0 works. */
/* ALWAYS make this window active in this case, because of 'activate'
toggle below. This is kinda screwy, but it works. */
win_activate (gstate, win);
pv = (polyview_t *)WIN_IMAGE(win);
/* Handle active/private and blast. */
switch (XmxExtractToken ((int)client_data))
{
case PV_PVIEW_BLAST:
PLAYAFILE ("/usr/lib/sounds/prosonus/musictags/jar.aiff");
parse_line (gstate, "blast image", TRUE);
break;
case PV_PVIEW_ACTIVE:
/* Never let the user make a window inactive -- making this
window active, above, should handle that. */
PLAYAFILE ("/usr/lib/sounds/prosonus/instr/conga_hi_rim.aiff");
break;
case PV_PVIEW_PRIVATE:
PLAYAFILE ("/usr/lib/sounds/prosonus/instr/conga_hi_rim.aiff");
break;
}
return;
}
/* ------------------------------------------------------------------------ */
/* ---------------------------- EVENT HANDLERS ---------------------------- */
/* ------------------------------------------------------------------------ */
/* File-local variables for picking mode; unclean, but what
the hell, we'll never be picking in more than one window
at a time anyway. */
static long ix, iy;
static long cx, cy;
static long px, py;
/* We gotta store the goddamn animation parameters locally
and set the real ones to 0 in pick mode, else picking won't
work with 'time forward' going. */
static long temp_forward, temp_reverse;
/* ---------------------- GUIpolyviewMotion1Handler ----------------------- */
static XmxEventHandler (GUIpolyviewMotion1Handler)
{
/* We get any button-1-down-with-motion events. */
window_t *win;
polyview_t *pv;
/* Do the pick shit. */
if (event->xmotion.state & Button1MotionMask)
{
/* Go get the window from the state's window list. */
win = find_window_by_id (gstate, XmxExtractUniqid ((int)client_data));
assert (win != NULL);
pv = (polyview_t *)WIN_IMAGE(win);
/* Get the new mouse location. */
cx = event->xmotion.x;
cy = pv->dv_height - 1 - event->xmotion.y;
/* If the mouse has moved, redraw the rubber band box and */
/* test label. */
if ((px != cx) || (py != cy))
{
#ifdef __sgi
/* Erase the old rubberband box and draw the new box. */
color (0);
recti(ix, iy, px, py);
color (1);
recti(ix, iy, cx, cy);
/* Place the type of operation in the window. */
cmov2i(2,2);
switch (win->pickmode)
{
case PICK_VERTEX:
charstr("PICK VERTEX");
break;
case PICK_EDGE:
charstr("PICK EDGE");
break;
case PICK_FACE:
charstr("PICK FACE");
break;
case PICK_OBJECT:
charstr("PICK OBJECT");
break;
}
#endif /* __sgi */
/* Update the "previous" mouse position. */
px = cx;
py = cy;
}
}
return;
}
/* ---------------------- GUIpolyviewMotion2Handler ----------------------- */
static XmxEventHandler (GUIpolyviewMotion2Handler)
{
/* We get any button-down-with-motion events. */
window_t *win;
polyview_t *pv;
float CM[DIMS], V[DIMS];
float old_half;
int shft_tmp;
/* Rotate scene. */
if (event->xmotion.state & Button2MotionMask)
{
/* Go get the window from the state's window list. */
win = find_window_by_id (gstate, XmxExtractUniqid ((int)client_data));
assert (win != NULL);
pv = (polyview_t *)WIN_IMAGE(win);
/* We don't need to activate the window here, since it will have
been activated in GUIpolyviewButtonPressHandler and we know
that the active window's not going to be changed before the button
is released. */
/* Get the new mouse location. */
CM[X] = event->xmotion.x;
CM[Y] = pv->dv_height - 1 - event->xmotion.y;
/* If shift key went up or down, do things. */
if (win->shift_changed)
{
win->shift_changed = 0;
win->CI[X] = CM[X];
win->CI[Y] = CM[Y];
win->rho_v = win->rho;
win->theta_v = win->theta;
win->phi_v = win->phi;
}
if (win->shifted)
{
/* Calculate new from point. */
win->rho = win->rho_v +
WIN_MAXWIDTH(win)*(CM[Y] - win->CI[Y])/win->radius;
if (win->rho < 0.05)
win->rho = 0.05;
}
else
{
win->theta = win->theta_v - PI*(CM[X]- win->CI[X])/win->radius;
win->phi = win->phi_v + PI*(CM[Y]- win->CI[Y])/win->radius;
old_half = win->half;
win->half = fsin(win->phi);
/* If the z axis is crossed, invert the twist value.
Is this even consequential? */
if (((win->half >= 0.0) && (old_half < 0.0)) ||
((win->half <= 0.0) && (old_half > 0.0)))
{
win->twist_tmp = win->twist_tmp - 1800;
if (win->twist_tmp < 0)
win->twist_tmp += 3600;
}
}
sphere_to_cart(win->rho, win->theta, win->phi,
&V[X], &V[Y], &V[Z]);
WIN_CFROM(win)[X] = WIN_AT(win)[X] + V[X];
WIN_CFROM(win)[Y] = WIN_AT(win)[Y] + V[Y];
WIN_CFROM(win)[Z] = WIN_AT(win)[Z] + V[Z];
WIN_SFROM(win)[RHO] = win->rho;
WIN_SFROM(win)[THETA] = win->theta;
WIN_SFROM(win)[PHI] = win->phi;
set_redraw (gstate, win);
}
return;
}
/* ------------------- GUIpolyviewButtonReleaseHandler ------------------- */
static XmxEventHandler (GUIpolyviewButtonReleaseHandler)
{
window_t *win;
polyview_t *pv;
char line[MAXLINELEN];
/* Go get the window from the state's window list. */
win = find_window_by_id (gstate, XmxExtractUniqid ((int)client_data));
assert (win != NULL);
pv = (polyview_t *)WIN_IMAGE(win);
/* Have to let Xmx know what this Uniqid is. */
XmxSetUniqid (win->id);
if (event->xbutton.button == Button1)
{
/* Remove the motion handler for this window --- we must match
proc and client_data for this to work. */
XmxRemoveEventHandler
(pv->drawing_volume, Button1MotionMask, GUIpolyviewMotion1Handler, 0);
/* Also commit suicide. This should work... */
XmxRemoveEventHandler
(pv->drawing_volume, ButtonReleaseMask,
GUIpolyviewButtonReleaseHandler, 0);
#ifdef __sgi
/* We're still in overlay mode. */
color (0);
clear ();
zbuffer (TRUE);
#endif /* __sgi */
/* Pop out of overlay mode. */
XmxWinset (pv->drawing_volume);
/* This is a bad idea because we will have gone into single matrix
mode and back out during pick, right? */
popmatrix ();
popviewport ();
/* Ensure that ix < cx and iy < cy. */
if (ix > cx)
{
int temp = ix;
ix = cx;
cx = temp;
}
if (iy > cy)
{
int temp = iy;
iy = cy;
cy = temp;
}
PickRegion (gstate, win, ix, iy, cx, cy, win->shifted, 0);
/* Restore animation for this window. */
WIN_FORWARD(win) = temp_forward;
WIN_REVERSE(win) = temp_reverse;
/* Turn actions back on. */
gstate->no_actions = 0;
}
if (event->xbutton.button == Button2)
{
/* Remove the motion handler for this window --- we must match
proc and client_data for this to work. */
XmxRemoveEventHandler
(pv->drawing_volume, Button2MotionMask, GUIpolyviewMotion2Handler, 0);
/* Also commit suicide. This should work... */
XmxRemoveEventHandler
(pv->drawing_volume, ButtonReleaseMask,
GUIpolyviewButtonReleaseHandler, 0);
/* Echo the final position to the transcript file, if any. */
/* Also add command to history list in command widget. */
if (gstate->transcript_fp != NULL)
{
fprintf(gstate->transcript_fp, "move camera %e %e %e %d\n",
WIN_CFROM(win)[X],
WIN_CFROM(win)[Y],
WIN_CFROM(win)[Z],
win->twist_tmp);
fflush (gstate->transcript_fp);
}
sprintf (line, "move camera %e %e %e %d\0",
WIN_CFROM(win)[X],
WIN_CFROM(win)[Y],
WIN_CFROM(win)[Z],
win->twist_tmp);
GUIaddCommand (line);
/* If a fast drawing function has been specified, undo it. */
if (win->use_fastdraw)
{
/* Turn off fast dragging and ask for yet another redraw. */
win->use_fastdraw = FALSE;
set_redraw(gstate, win);
}
}
return;
}
/* -------------------- GUIpolyviewButtonPressHandler --------------------- */
static XmxEventHandler (GUIpolyviewButtonPressHandler)
{
/* We get incoming button presses under the assumption that
the appropriate motion handler hasn't been installed yet. */
window_t *win;
polyview_t *pv;
/* Go get the window from the state's window list. */
win = find_window_by_id (gstate, XmxExtractUniqid ((int)client_data));
assert (win != NULL);
/* Make the window active; this won't put an 'activate window'
message in the history list, which is how Polyview 2.0 works. */
if (win != gstate->active_windows)
win_activate (gstate, win);
pv = (polyview_t *)WIN_IMAGE(win);
/* Use this window's uniqid for any event handlers. */
XmxSetUniqid (win->id);
/* Breakdown by button. */
if (event->xbutton.button == Button1 && WinHasData (win))
{
XmxWinset (pv->drawing_volume);
#ifdef __sgi
/* Go into overlay planes; no Zbuffer, and clear it out. */
GLXwinset (XtDisplay (pv->drawing_volume),
overlayWindow (pv->drawing_volume));
color (0);
clear ();
#endif
zbuffer (FALSE);
pushviewport ();
pushmatrix ();
ortho2 (0.0, (float)(pv->dv_width), 0.0, (float)(pv->dv_height));
/* Load static variables for initial position. */
ix = cx = event->xbutton.x;
iy = cy = pv->dv_height - 1 - event->xbutton.y;
px = -1;
py = -1;
/* Now we're in picking mode. Load up the
event handlers. */
/* Install the button 1 motion handler for this window. */
XmxAddEventHandler
(pv->drawing_volume, Button1MotionMask, GUIpolyviewMotion1Handler, 0);
/* Install the button 1 release handler for this window. */
XmxAddEventHandler
(pv->drawing_volume, ButtonReleaseMask,
GUIpolyviewButtonReleaseHandler, 0);
/* Store the animation parameters for this window and
set 'em to 0. */
temp_forward = WIN_FORWARD(win);
temp_reverse = WIN_REVERSE(win);
WIN_FORWARD(win) = WIN_REVERSE(win) = 0;
/* Turn off actions. */
gstate->no_actions = 1;
}
if (event->xbutton.button == Button2)
{
/* Install the button 2 motion handler for this window. */
XmxAddEventHandler
(pv->drawing_volume, Button2MotionMask, GUIpolyviewMotion2Handler, 0);
/* Install the button 2 release handler for this window. */
XmxAddEventHandler
(pv->drawing_volume, ButtonReleaseMask,
GUIpolyviewButtonReleaseHandler, 0);
/* If a fast drawing function has been specified for this
window, then use it. */
win->use_fastdraw = TRUE;
/* Load initial calculations for transformation
into the window struct. */
win->radius = (float)MIN(win->cx, win->cy);
win->CI[X] = (float)(event->xbutton.x);
win->CI[Y] = (float)(pv->dv_height - 1 - event->xbutton.y);
win->rho = WIN_SFROM(win)[RHO];
win->theta = WIN_SFROM(win)[THETA];
win->phi = WIN_SFROM(win)[PHI];
win->rho_v = win->rho;
win->theta_v = win->theta;
win->phi_v = win->phi;
win->half = sin (win->phi_v);
/* Get a redraw at least to draw with the fastdraw function. */
set_redraw (gstate, win);
}
return;
}
/* ------------------------------------------------------------------------ */
/* ------------------------------------------------------------------------ */
/* ------------------------------------------------------------------------ */
/* This is going to cause collisions between movement functionality
of local and remote user, if they operate at the same time.
That's because it's a hack, stupid. */
void remote_movecursor (state_t *state, window_t *win, float fx, float fy)
{
int x = (int)fx, y = (int)fy;
polyview_t *pv;
fprintf (stderr, "CALLED %f %f %d %d\n", fx, fy, x, y);
pv = (polyview_t *)WIN_IMAGE(win);
/* Are we not moving yet? */
if (win->use_fastdraw == FALSE)
{
/* If a fast drawing function has been specified for this
window, then use it. */
win->use_fastdraw = TRUE;
/* Load initial calculations for transformation
into the window struct. */
win->radius = (float)MIN(win->cx, win->cy);
win->CI[X] = (float)(x);
win->CI[Y] = (float)(pv->dv_height - 1 - y);
win->rho = WIN_SFROM(win)[RHO];
win->theta = WIN_SFROM(win)[THETA];
win->phi = WIN_SFROM(win)[PHI];
win->rho_v = win->rho;
win->theta_v = win->theta;
win->phi_v = win->phi;
win->half = sin (win->phi_v);
/* Get a redraw at least to draw with the fastdraw function. */
set_redraw (gstate, win);
}
else
{
float CM[DIMS], V[DIMS];
float old_half;
int shft_tmp;
/* Actually move. */
/* Get the new mouse location. */
CM[X] = x;
CM[Y] = pv->dv_height - 1 - y;
win->theta = win->theta_v - PI*(CM[X]- win->CI[X])/win->radius;
win->phi = win->phi_v + PI*(CM[Y]- win->CI[Y])/win->radius;
old_half = win->half;
win->half = fsin(win->phi);
/* If the z axis is crossed, invert the twist value.
Is this even consequential? */
if (((win->half >= 0.0) && (old_half < 0.0)) ||
((win->half <= 0.0) && (old_half > 0.0)))
{
win->twist_tmp = win->twist_tmp - 1800;
if (win->twist_tmp < 0)
win->twist_tmp += 3600;
}
sphere_to_cart(win->rho, win->theta, win->phi,
&V[X], &V[Y], &V[Z]);
WIN_CFROM(win)[X] = WIN_AT(win)[X] + V[X];
WIN_CFROM(win)[Y] = WIN_AT(win)[Y] + V[Y];
WIN_CFROM(win)[Z] = WIN_AT(win)[Z] + V[Z];
WIN_SFROM(win)[RHO] = win->rho;
WIN_SFROM(win)[THETA] = win->theta;
WIN_SFROM(win)[PHI] = win->phi;
set_redraw (gstate, win);
}
return;
}
void remote_movecursorend (state_t *state, window_t *win)
{
char line[MAXLINELEN];
/* Echo the final position to the transcript file, if any. */
/* Also add command to history list in command widget. */
if (gstate->transcript_fp != NULL)
{
fprintf(gstate->transcript_fp, "move camera %e %e %e %d\n",
WIN_CFROM(win)[X],
WIN_CFROM(win)[Y],
WIN_CFROM(win)[Z],
win->twist_tmp);
fflush (gstate->transcript_fp);
}
sprintf (line, "move camera %e %e %e %d\0",
WIN_CFROM(win)[X],
WIN_CFROM(win)[Y],
WIN_CFROM(win)[Z],
win->twist_tmp);
GUIaddCommand (line);
win->use_fastdraw = FALSE;
set_redraw (gstate, win);
return;
}
/* --------------------------- GUIpviewInputCB ---------------------------- */
#ifdef __sgi
static XmxCallback (GUIpviewInputCB)
{
window_t *win;
polyview_t *pv;
int _bufsize = 3, _count;
char _buffer[3];
KeySym _key;
XComposeStatus _cs;
XEvent *event = ((XmDrawingAreaCallbackStruct *)call_data)->event;
/* Go get the window from the state's window list. */
win = find_window_by_id (gstate, XmxExtractUniqid ((int)client_data));
assert (win != NULL);
/* Make the window active; this won't put an 'activate window'
message in the history list, which is how Polyview 2.0 works. */
if (win != gstate->active_windows)
win_activate (gstate, win);
pv = (polyview_t *)WIN_IMAGE(win);
if (((XmDrawingAreaCallbackStruct *)call_data)->reason == XmCR_INPUT)
{
if (event->xany.type == KeyPress)
{
/* Go get ascii translation. */
_count = XLookupString (&(event->xkey), _buffer, _bufsize,
&_key, &_cs);
/* Insert trailing Nil. */
_buffer[_count] = '\0';
/* Ah, let's just use the KeySym directly. */
if (_key == XK_Shift_L || _key == XK_Shift_R)
{
win->shifted = 1;
win->shift_changed = 1;
}
}
else if (event->xany.type == KeyRelease)
{
/* Go get ascii translation. */
_count = XLookupString (&(event->xkey), _buffer, _bufsize,
&_key, &_cs);
/* Insert trailing Nil. */
_buffer[_count] = '\0';
/* Ah, let's just use the KeySym directly. */
if (_key == XK_Shift_L || _key == XK_Shift_R)
{
win->shifted = 0;
win->shift_changed = 1;
}
}
}
return;
}
#endif /* __sgi */
/* ------------------------------------------------------------------------ */
/* ---------------------------- MENUBAR STRUCT ---------------------------- */
/* ------------------------------------------------------------------------ */
static XmxMenubarStruct PviewFileMenu[] =
{
{ "Load Vset...", 'V', GUIpolyviewMenubarCB, PV_PVIEW_LOAD_VSET },
{ "Send Vset", 'S', GUIpolyviewMenubarCB, PV_PVIEW_DTM_SEND },
{ "----" },
{ "Data Load", 'L', GUIpolyviewMenubarCB, PV_PVIEW_DATA_LOAD },
{ "----" },
{ "Save HDF...", 'H', GUIpolyviewMenubarCB, PV_PVIEW_SAVE_HDF },
{ "Save Ray...", 'y', GUIpolyviewMenubarCB, PV_PVIEW_SAVE_RAY },
{ "Save RGB...", 'G', GUIpolyviewMenubarCB, PV_PVIEW_SAVE_RGB },
#ifdef RENDERMAN
{ "Save Renderman...", 'm', GUIpolyviewMenubarCB, PV_PVIEW_SAVE_RENDERMAN },
#endif
{ "----" },
{ "Reset", 'R', GUIpolyviewMenubarCB, PV_PVIEW_RESET },
{ "----" },
{ "Close Window", 'C', GUIpolyviewMenubarCB, PV_PVIEW_CLOSE_WINDOW },
{ "Exit Program...", 'E', GUImainMenubarCB, PV_EXIT_PROGRAM },
{ NULL },
};
static XmxMenubarStruct PviewWindowsMenu[] =
{
{ "Open Polyview...", 'O', GUImainMenubarCB, PV_OPEN_POLYVIEW },
{ "Open Palette...", 'P', GUImainMenubarCB, PV_OPEN_PALETTE },
{ "Open Info...", 'I', GUImainMenubarCB, PV_OPEN_INFO },
{ "Open Time...", 'T', GUImainMenubarCB, PV_OPEN_TIME },
{ NULL },
};
static XmxMenubarStruct PviewDrawmodeMenu[] =
{
{ "<Vertices", 'V', GUIpolyviewMenubarCB, PV_PVIEW_DRAW_VERTICES },
{ "<Edges", 'E', GUIpolyviewMenubarCB, PV_PVIEW_DRAW_EDGES },
{ "<Hidden Edges", 'H', GUIpolyviewMenubarCB, PV_PVIEW_DRAW_HIDDEN },
{ "<Faces", 'F', GUIpolyviewMenubarCB, PV_PVIEW_DRAW_FACES },
{ "<Outlined Faces", 'O', GUIpolyviewMenubarCB, PV_PVIEW_DRAW_OUTFACES },
{ NULL },
};
static XmxMenubarStruct PviewDragmodeMenu[] =
{
{ "<Nothing", 'N', GUIpolyviewMenubarCB, PV_PVIEW_DRAG_NOTHING },
{ "<Box", 'B', GUIpolyviewMenubarCB, PV_PVIEW_DRAG_BOX },
{ "<Vertices", 'V', GUIpolyviewMenubarCB, PV_PVIEW_DRAG_VERTICES },
{ "<Edges", 'E', GUIpolyviewMenubarCB, PV_PVIEW_DRAG_EDGES },
{ "<Hidden Edges", 'H', GUIpolyviewMenubarCB, PV_PVIEW_DRAG_HIDDEN },
{ "<Faces", 'F', GUIpolyviewMenubarCB, PV_PVIEW_DRAG_FACES },
{ "<Outlined Faces", 'O', GUIpolyviewMenubarCB, PV_PVIEW_DRAG_OUTFACES },
{ "----" },
{ "<Same As Draw", 'S', GUIpolyviewMenubarCB, PV_PVIEW_DRAG_SAMEASDRAW },
{ NULL },
};
static XmxMenubarStruct PviewLightMenu[] =
{
{ "<Light Off", 'O', GUIpolyviewMenubarCB, PV_PVIEW_LIGHT_OFF },
{ "----" },
{ "<Light One", 'L', GUIpolyviewMenubarCB, PV_PVIEW_LIGHT_ONE },
{ "<Light Two", 'T', GUIpolyviewMenubarCB, PV_PVIEW_LIGHT_TWO },
{ "<Light Three", 'h', GUIpolyviewMenubarCB, PV_PVIEW_LIGHT_THREE },
{ "<Light X", 'X', GUIpolyviewMenubarCB, PV_PVIEW_LIGHT_X },
{ "<Light Y", 'Y', GUIpolyviewMenubarCB, PV_PVIEW_LIGHT_Y },
{ "<Light Z", 'Z', GUIpolyviewMenubarCB, PV_PVIEW_LIGHT_Z },
{ "----" },
{ "#TwoSide Light", 'S', GUIpolyviewMenubarCB, PV_PVIEW_LIGHT_TWOSIDE },
{ NULL },
};
static XmxMenubarStruct PviewProjMenu[] =
{
{ "<Perspective", 'P', GUIpolyviewMenubarCB, PV_PVIEW_PROJ_PERSPECTIVE },
{ "<Orthographic", 'O', GUIpolyviewMenubarCB, PV_PVIEW_PROJ_ORTHOGRAPHIC },
{ NULL },
};
static XmxMenubarStruct PviewShadeMenu[] =
{
{ "<Gouraud", 'G', GUIpolyviewMenubarCB, PV_PVIEW_SHADE_GOURAUD },
{ "<Flat", 'F', GUIpolyviewMenubarCB, PV_PVIEW_SHADE_FLAT },
{ NULL },
};
static XmxMenubarStruct PviewRenderMenu[] =
{
{ "Draw", 'D', NULL, NULL, PviewDrawmodeMenu },
{ "Drag", 'g', NULL, NULL, PviewDragmodeMenu },
{ "----" },
{ "Light", 'L', NULL, NULL, PviewLightMenu },
{ "----" },
{ "Line Width...", 'W', GUIpolyviewMenubarCB, PV_PVIEW_POPUP_LINEWIDTH },
{ "Outline Color...", 'O', GUIpolyviewMenubarCB, PV_PVIEW_POPUP_OUTLINE },
{ "Vertex Spheres...", 'S', GUIpolyviewMenubarCB, PV_PVIEW_POPUP_SPHERE },
{ "----" },
{ "Projection", 'P', NULL, NULL, PviewProjMenu },
{ "Shademodel", 'S', NULL, NULL, PviewShadeMenu },
{ NULL },
};
static XmxMenubarStruct PviewAxesMenu[] =
{
{ "<Large", 'L', GUIpolyviewMenubarCB, PV_PROPS_AXES_LARGE },
{ "<Small", 'S', GUIpolyviewMenubarCB, PV_PROPS_AXES_SMALL },
{ "----" },
{ "<Off", 'O', GUIpolyviewMenubarCB, PV_PROPS_AXES_OFF },
{ NULL },
};
static XmxMenubarStruct PviewBoxMenu[] =
{
{ "<All", 'A', GUIpolyviewMenubarCB, PV_PROPS_BOX_EDGESFACES },
{ "----" },
{ "<Faces", 'F', GUIpolyviewMenubarCB, PV_PROPS_BOX_FACES },
{ "<Edges", 'E', GUIpolyviewMenubarCB, PV_PROPS_BOX_EDGES },
{ "----" },
{ "<Off", 'O', GUIpolyviewMenubarCB, PV_PROPS_BOX_OFF },
{ NULL },
};
static XmxMenubarStruct PviewGridMenu[] =
{
{ "All", 'A', GUIpolyviewMenubarCB, PV_PROPS_GRID_ALL },
{ "----" },
{ "#X Y", 'X', GUIpolyviewMenubarCB, PV_PROPS_GRID_XY },
{ "#Y Z", 'Y', GUIpolyviewMenubarCB, PV_PROPS_GRID_YZ },
{ "#X Z", 'Z', GUIpolyviewMenubarCB, PV_PROPS_GRID_XZ },
{ "----" },
{ "Off", 'O', GUIpolyviewMenubarCB, PV_PROPS_GRID_OFF },
{ NULL },
};
static XmxMenubarStruct PviewShadowMenu[] =
{
{ "All", 'A', GUIpolyviewMenubarCB, PV_PROPS_SHADOW_ALL },
{ "----" },
{ "#X Y", 'X', GUIpolyviewMenubarCB, PV_PROPS_SHADOW_XY },
{ "#Y Z", 'Y', GUIpolyviewMenubarCB, PV_PROPS_SHADOW_YZ },
{ "#X Z", 'Z', GUIpolyviewMenubarCB, PV_PROPS_SHADOW_XZ },
{ "----" },
{ "Off", 'O', GUIpolyviewMenubarCB, PV_PROPS_SHADOW_OFF },
{ NULL },
};
static XmxMenubarStruct PviewPropsMenu[] =
{
{ "Axes", 'A', NULL, NULL, PviewAxesMenu },
{ "Box", 'B', NULL, NULL, PviewBoxMenu },
{ "Grid", 'G', NULL, NULL, PviewGridMenu },
{ "Shadow", 'S', NULL, NULL, PviewShadowMenu },
{ "#Legend", 'L', GUIpolyviewMenubarCB, PV_PROPS_LEGEND },
{ "#Credits", 'C', GUIpolyviewMenubarCB, PV_PROPS_CREDITS },
{ "----" },
{ "All Off", 'O', GUIpolyviewMenubarCB, PV_PROPS_ALL_OFF },
{ NULL },
};
static XmxMenubarStruct PviewTimeMenu[] =
{
{ "Forward", 'F', GUIpolyviewMenubarCB, PV_PVIEW_TIME_FORWARD },
{ "Forward Step", 'o', GUIpolyviewMenubarCB, PV_PVIEW_TIME_FORWARDSTEP },
{ "Stop", 'S', GUIpolyviewMenubarCB, PV_PVIEW_TIME_STOP },
{ "Reverse Step", 'e', GUIpolyviewMenubarCB, PV_PVIEW_TIME_REVERSESTEP },
{ "Reverse", 'R', GUIpolyviewMenubarCB, PV_PVIEW_TIME_REVERSE },
{ "----" },
{ "Reset", 't', GUIpolyviewMenubarCB, PV_PVIEW_TIME_RESET },
{ NULL },
};
static XmxMenubarStruct PviewSelectMenu[] =
{
{ "<Vertices", 'V', GUIpolyviewMenubarCB, PV_PVIEW_SELECT_VERTICES },
{ "<Faces", 'F', GUIpolyviewMenubarCB, PV_PVIEW_SELECT_FACES },
{ "<Objects", 'O', GUIpolyviewMenubarCB, PV_PVIEW_SELECT_OBJECTS },
{ "----" },
{ "All", 'A', GUIpolyviewMenubarCB, PV_PVIEW_SELECT_ALL },
{ NULL },
};
static XmxMenubarStruct PviewHelpMenu[] =
{
{ "About", 'A', GUImainMenubarCB, PV_HELP_ABOUT },
{ "On Commands", 'C', GUImainMenubarCB, PV_HELP_ONCOMMANDS},
{ "On Window", 'W', GUIpolyviewMenubarCB, PV_PVIEW_HELP_ONWINDOW },
{ NULL },
};
static XmxMenubarStruct PviewMenu[] =
{
{ "File", 'F', NULL, NULL, PviewFileMenu },
{ "Windows", 'W', NULL, NULL, PviewWindowsMenu },
{ "Render", 'R', NULL, NULL, PviewRenderMenu },
{ "Props", 'P', NULL, NULL, PviewPropsMenu },
{ "Time", 'T', NULL, NULL, PviewTimeMenu },
{ "Select", 'S', NULL, NULL, PviewSelectMenu },
{ "Help", 'H', NULL, NULL, PviewHelpMenu },
{ NULL },
};
/* ------------------------------------------------------------------------ */
/* ------------------------- GL WIDGET CALLBACKS -------------------------- */
/* ------------------------------------------------------------------------ */
/* --------------------------- GUIpviewRedrawCB --------------------------- */
XmxCallback (GUIpviewRedrawCB)
{
window_t *win;
/* This should get us the window_t struct corresponding to the
window that triggered the callback. */
win = find_window_by_id (gstate, XmxExtractUniqid ((int)client_data));
assert (win != NULL);
set_redraw (gstate, win);
return;
}
/* --------------------------- GUIpviewGinitCB ---------------------------- */
XmxCallback (GUIpviewGinitCB)
{
window_t *win;
polyview_t *pv;
/* This should get us the window_t struct corresponding to the
window that triggered the callback. */
win = find_window_by_id (gstate, XmxExtractUniqid ((int)client_data));
assert (win != NULL);
/* Grab the polyview image for the window. */
pv = (polyview_t *)WIN_IMAGE(win);
/* ---> This callback is supposed to be hit when the Widget
is first realized. */
/* Focus on this window. */
XmxWinset (w);
/* Set up initial parameters. */
doublebuffer ();
RGBmode ();
/* Set up zbuffering. */
zbuffer(TRUE);
/* Go into MVIEWING mode for lighting. */
mmode (MVIEWING);
#ifdef __sgi
XmxInstallColormapsWithOverlay (gstate->base, pv->drawing_volume);
#else /* not __sgi */
XmxInstallColormaps (gstate->base, pv->drawing_volume);
#endif /* not __sgi */
if (!(gstate->gl_initialized))
{
/* This is now different from the palette window... */
gstate->gl_initialized = 1;
/* Right now lighting and patterns init is here since we know
this is the first GL dialog to be opened. */
init_lighting ();
init_patterns ();
init_zbuffer ();
}
/* Reverse orientation of Z-buffer (was 0x7fff..., 0). */
lsetdepth (gstate->zmax, gstate->zmin);
zfunction (ZF_GEQUAL);
#ifdef __sgi
/* Handle the overlays. */
GLXwinset (XtDisplay (w), overlayWindow (w));
mapcolor (0, 0, 0, 0);
mapcolor (1, 255, 255, 255);
#endif
/* Go back to regular window, just to be safe. */
XmxWinset (w);
/* This should be all that's needed; the rest of the work takes
place in redraw_polyview, right? */
/* We get a redraw callback here. */
return;
}
/* --------------------------- GUIpviewResizeCB --------------------------- */
XmxCallback (GUIpviewResizeCB)
{
window_t *win;
polyview_t *pv;
/* This should get us the window_t struct corresponding to the
window that triggered the callback. */
win = find_window_by_id (gstate, XmxExtractUniqid ((int)client_data));
assert (win != NULL);
/* Grab the polyview image for the window. */
pv = (polyview_t *)WIN_IMAGE(win);
/* Do a GL focus on the window as we get it from the callback. */
XmxWinset (w);
/* Store the new width and height in the window image. */
#ifdef __sgi
pv->dv_width = ((GlxDrawCallbackStruct *)call_data)->width;
pv->dv_height = ((GlxDrawCallbackStruct *)call_data)->height;
#endif
#ifdef _IBMR2
{
Dimension x, y;
XmxSetArg (XmNwidth, &x);
XmxSetArg (XmNheight, &y);
XtGetValues (w, Xmx_wargs, Xmx_n);
pv->dv_width = x;
pv->dv_height = y;
}
#endif
/* Go update the rest of Calvert's data structures. */
win->width = pv->dv_width;
win->height = pv->dv_height;
win->cx = win->width / 2;
win->cy = win->height / 2;
/* Explicitly avoid reshapeviewport by retrieving new
geometry from call_data. */
viewport
(0, (Screencoord)pv->dv_width - 1, 0, (Screencoord)pv->dv_height - 1);
#ifdef __sgi
/* Repeat the process for the overlay window. */
GLXwinset (XtDisplay (w), overlayWindow (w));
viewport
(0, (Screencoord)pv->dv_width - 1, 0, (Screencoord)pv->dv_height - 1);
#endif
/* We get a redraw callback here. */
return;
}
/* -------------------------- win_open_polyview --------------------------- */
#ifdef __sgi
static GLXconfig polyviewGlxConfig[] =
{
{ GLX_NORMAL, GLX_DOUBLE, TRUE },
{ GLX_NORMAL, GLX_RGB, TRUE },
{ GLX_NORMAL, GLX_ZSIZE, GLX_NOCONFIG },
{ GLX_OVERLAY, GLX_BUFSIZE, 2},
{ 0, 0, 0 },
};
#endif /* __sgi */
int win_open_polyview(state_t *state, window_t *win, char *name)
{
/* Just for the hell of it, we use the 'win' pointer passed in. */
/* window_t *win; */
polyview_t *pv;
Widget button_form, drawing_frame;
char line[MAXLINELEN];
/* Uh oh, what if we got an unnamed window? */
if (name[0] == '\0')
name = "Unnamed";
/* Create a new win */
win = add_window
(state, name, POLYVIEW, init_polyview, redraw_polyview, animate_polyview,
event_polyview, notify_polyview, destroy_polyview);
/* Add polyview structure to the new window. */
add_poly(state, win);
/* Grab the polyview struct from the window struct. We have created
it in add_poly above. */
pv = (polyview_t *)WIN_IMAGE(win);
/* Choose a uniqid and create the window. */
win->id = XmxMakeNewUniqid ();
XmxSetUniqid (win->id);
sprintf (line, "Polyview 3.1: %s\0", name);
win->base = XmxMakeFormDialog (state->base, line);
/* Identify the window for debugging purposes. */
win->debug_str = "***Polyview Window";
/* Make the menubar first. */
pv->menubar = XmxRMakeMenubar (win->base, PviewMenu);
/* Initial menubar options. */
pv->current_select_token = PV_PVIEW_SELECT_FACES;
XmxRSetToggleState (pv->menubar, pv->current_select_token, XmxSet);
/* Make button_form and buttons. */
XmxSetArg (XmNverticalSpacing, 5);
XmxSetArg (XmNhorizontalSpacing, 10);
button_form = XmxMakeForm (win->base);
pv->active = XmxMakeToggleButton
(button_form, "Active", GUIpolyviewWindowCB, PV_PVIEW_ACTIVE);
pv->dtmlockout = XmxMakeToggleButton
(button_form, "Private", GUIpolyviewWindowCB, PV_PVIEW_PRIVATE);
XmxSetSensitive (pv->dtmlockout, XmxUnsensitive);
XmxSetToggleButton (pv->active, XmxSet);
XmxSetToggleButton (pv->dtmlockout, XmxUnset);
pv->blast = XmxMakePushButton
(button_form, "Blast Image", GUIpolyviewWindowCB, PV_PVIEW_BLAST);
/* Constraints for button_form. */
XmxSetConstraints
(pv->active, XmATTACH_FORM, XmATTACH_FORM, XmATTACH_FORM, XmATTACH_NONE,
NULL, NULL, NULL, NULL);
XmxSetConstraints
(pv->blast, XmATTACH_FORM, XmATTACH_FORM, XmATTACH_WIDGET,
XmATTACH_NONE, NULL, NULL, pv->active, NULL);
XmxSetConstraints
(pv->dtmlockout, XmATTACH_FORM, XmATTACH_FORM, XmATTACH_NONE,
XmATTACH_FORM, NULL, NULL, NULL, NULL);
/* Make the frame for the drawing volume. */
drawing_frame = XmxMakeFrame (win->base, XmxShadowOut);
/* Make the drawing volume itself. */
pv->dv_width = win->width = 640;
pv->dv_height = win->height = 512;
win->cx = win->width / 2;
win->cy = win->height / 2;
#ifdef __sgi
if (getgdesc (GD_BITS_OVER_SNG_CMODE) < 2)
use_pups = TRUE;
if (use_pups)
polyviewGlxConfig[3].buffer = GLX_POPUP;
XmxSetArg (use_pups ? GlxNusePopup : GlxNuseOverlay, TRUE);
pv->drawing_volume = XmxMakeDrawingVolume
(drawing_frame, pv->dv_width, pv->dv_height, polyviewGlxConfig,
GUIpviewRedrawCB, GUIpviewResizeCB, GUIpviewGinitCB);
XtAddCallback
(pv->drawing_volume,
use_pups ? GlxNpopupExposeCallback : GlxNoverlayExposeCallback,
overlayExposeCB, 0);
#endif
#ifdef _IBMR2
pv->drawing_volume = XmxMakeDrawingVolume
(drawing_frame, pv->dv_width, pv->dv_height,
GUIpviewRedrawCB, GUIpviewResizeCB, GUIpviewGinitCB);
#endif
/* Add the event handler for button presses. The buttonpress
handler spawns off motion and release handlers as necessary. */
XmxAddEventHandler
(pv->drawing_volume, ButtonPressMask, GUIpolyviewButtonPressHandler, 0);
#ifdef __sgi
/* !@#%!@#%!@#%!@# IBM */
/* Use the input callback for keyboard events. */
XmxAddCallback (pv->drawing_volume, XmNinputCallback, GUIpviewInputCB, 0);
#endif
/* Constraints for base. */
XmxSetConstraints
(pv->menubar->base, XmATTACH_FORM, XmATTACH_NONE, XmATTACH_FORM,
XmATTACH_FORM, NULL, NULL, NULL, NULL);
XmxSetConstraints
(button_form, XmATTACH_WIDGET, XmATTACH_NONE, XmATTACH_FORM, XmATTACH_FORM,
pv->menubar->base, NULL, NULL, NULL);
XmxSetConstraints
(drawing_frame, XmATTACH_WIDGET, XmATTACH_FORM, XmATTACH_FORM,
XmATTACH_FORM, button_form, NULL, NULL, NULL);
/* Set the default drawing function. Default rotation, scaling, and */
/* translation are maintained. */
WIN_DRAW(win) = draw_edges;
XFO_USED(WIN_ROT(win)) = TRUE;
XFO_USED(WIN_SCL(win)) = TRUE;
XFO_USED(WIN_TRN(win)) = TRUE;
XmxManageRemanage (win->base);
GUIpviewResetRender (state, win);
GUIpviewResetProps (state, win);
add_palette(state, win, NULL);
GUIpaletteResetBackdrop (state, win);
GUIpaletteResetPresets (state);
win_activate(state, win);
return ST_OKAY;
}